home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 1999 August / SGI Freeware 1999 August.iso / dist / fw_xemacs.idb / usr / freeware / lib / xemacs-20.4 / lisp / prim / files.el.z / files.el
Encoding:
Text File  |  1998-05-21  |  121.2 KB  |  3,100 lines

  1. ;;; files.el --- file input and output commands for XEmacs.
  2.  
  3. ;; Copyright (C) 1985-1987, 1992-1995, 1997 Free Software Foundation, Inc.
  4. ;; Copyright (C) 1995 Sun Microsystems.
  5.  
  6. ;; This file is part of XEmacs.
  7.  
  8. ;; XEmacs is free software; you can redistribute it and/or modify it
  9. ;; under the terms of the GNU General Public License as published by
  10. ;; the Free Software Foundation; either version 2, or (at your option)
  11. ;; any later version.
  12.  
  13. ;; XEmacs is distributed in the hope that it will be useful, but
  14. ;; WITHOUT ANY WARRANTY; without even the implied warranty of
  15. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16. ;; General Public License for more details.
  17.  
  18. ;; You should have received a copy of the GNU General Public License
  19. ;; along with XEmacs; see the file COPYING.  If not, write to the Free
  20. ;; Software Foundation, Inc. 59 Temple Place - Suite 330, Boston, MA
  21. ;; 02111-1307, USA.
  22.  
  23. ;;; Synched up with: FSF 19.34 [Partial].
  24. ;;; Warning: Merging this file is tough.  Beware.
  25.  
  26. ;;; Commentary:
  27.  
  28. ;; Defines most of XEmacs's file- and directory-handling functions,
  29. ;; including basic file visiting, backup generation, link handling,
  30. ;; ITS-id version control, load- and write-hook handling, and the like.
  31.  
  32. ;;; Code:
  33.  
  34. ;; XEmacs: Avoid compilation warnings.
  35. (defvar coding-system-for-read)
  36. (defvar buffer-file-coding-system)
  37.  
  38. (defgroup backup nil
  39.   "Backups of edited data files."
  40.   :group 'files)
  41.  
  42. (defgroup find-file nil
  43.   "Finding and editing files."
  44.   :group 'files)
  45.  
  46.  
  47. ;; XEmacs: In buffer.c
  48. ;(defconst delete-auto-save-files t
  49. ;  "*Non-nil means delete auto-save file when a buffer is saved or killed.")
  50.  
  51. ;; FSF has automount-dir-prefix.  Our directory-abbrev-alist is more general.
  52. ;; note: tmp_mnt bogosity conversion is established in paths.el.
  53. (defcustom directory-abbrev-alist nil
  54.   "*Alist of abbreviations for file directories.
  55. A list of elements of the form (FROM . TO), each meaning to replace
  56. FROM with TO when it appears in a directory name.
  57. This replacement is done when setting up the default directory of a
  58. newly visited file.  *Every* FROM string should start with \\\\` or ^.
  59.  
  60. Use this feature when you have directories which you normally refer to
  61. via absolute symbolic links or to eliminate automounter mount points
  62. from the beginning of your filenames.  Make TO the name of the link,
  63. and FROM the name it is linked to."
  64.   :type '(repeat (cons :format "%v"
  65.                :value ("\\`" . "")
  66.                (regexp :tag "From")
  67.                (regexp :tag "To")))
  68.   :group 'find-file)
  69.  
  70. ;;; Turn off backup files on VMS since it has version numbers.
  71. (defcustom make-backup-files (not (eq system-type 'vax-vms))
  72.   "*Non-nil means make a backup of a file the first time it is saved.
  73. This can be done by renaming the file or by copying.
  74.  
  75. Renaming means that XEmacs renames the existing file so that it is a
  76. backup file, then writes the buffer into a new file.  Any other names
  77. that the old file had will now refer to the backup file.  The new file
  78. is owned by you and its group is defaulted.
  79.  
  80. Copying means that XEmacs copies the existing file into the backup
  81. file, then writes the buffer on top of the existing file.  Any other
  82. names that the old file had will now refer to the new (edited) file.
  83. The file's owner and group are unchanged.
  84.  
  85. The choice of renaming or copying is controlled by the variables
  86. `backup-by-copying', `backup-by-copying-when-linked' and
  87. `backup-by-copying-when-mismatch'.  See also `backup-inhibited'."
  88.   :type 'boolean
  89.   :group 'backup)
  90.  
  91. ;; Do this so that local variables based on the file name
  92. ;; are not overridden by the major mode.
  93. (defvar backup-inhibited nil
  94.   "Non-nil means don't make a backup, regardless of the other parameters.
  95. This variable is intended for use by making it local to a buffer.
  96. But it is local only if you make it local.")
  97. (put 'backup-inhibited 'permanent-local t)
  98.  
  99. (defcustom backup-by-copying nil
  100.  "*Non-nil means always use copying to create backup files.
  101. See documentation of variable `make-backup-files'."
  102.  :type 'boolean
  103.  :group 'backup)
  104.  
  105. (defcustom backup-by-copying-when-linked nil
  106.  "*Non-nil means use copying to create backups for files with multiple names.
  107. This causes the alternate names to refer to the latest version as edited.
  108. This variable is relevant only if `backup-by-copying' is nil."
  109.  :type 'boolean
  110.  :group 'backup)
  111.  
  112. (defcustom backup-by-copying-when-mismatch nil
  113.   "*Non-nil means create backups by copying if this preserves owner or group.
  114. Renaming may still be used (subject to control of other variables)
  115. when it would not result in changing the owner or group of the file;
  116. that is, for files which are owned by you and whose group matches
  117. the default for a new file created there by you.
  118. This variable is relevant only if `backup-by-copying' is nil."
  119.   :type 'boolean
  120.   :group 'backup)
  121.  
  122. (defvar backup-enable-predicate
  123.   '(lambda (name)
  124.      (or (< (length name) 5)
  125.      (not (string-equal "/tmp/" (substring name 0 5)))))
  126.   "Predicate that looks at a file name and decides whether to make backups.
  127. Called with an absolute file name as argument, it returns t to enable backup.")
  128.  
  129. (defcustom buffer-offer-save nil
  130.   "*Non-nil in a buffer means offer to save the buffer on exit
  131. even if the buffer is not visiting a file.
  132. Automatically local in all buffers."
  133.   :type 'boolean
  134.   :group 'find-file)
  135. (make-variable-buffer-local 'buffer-offer-save)
  136.  
  137. ;; FSF uses normal defconst
  138. (defvaralias 'find-file-visit-truename 'find-file-use-truenames)
  139. (defvaralias 'find-file-existing-other-name 'find-file-compare-truenames)
  140.  
  141. (defcustom revert-without-query nil
  142.   "*Specify which files should be reverted without query.
  143. The value is a list of regular expressions.
  144. If the file name matches one of these regular expressions,
  145. then `revert-buffer' reverts the file without querying
  146. if the file has changed on disk and you have not edited the buffer."
  147.   :type '(repeat (regexp ""))
  148.   :group 'find-file)
  149.  
  150. (defvar buffer-file-number nil
  151.   "The device number and file number of the file visited in the current buffer.
  152. The value is a list of the form (FILENUM DEVNUM).
  153. This pair of numbers uniquely identifies the file.
  154. If the buffer is visiting a new file, the value is nil.")
  155. (make-variable-buffer-local 'buffer-file-number)
  156. (put 'buffer-file-number 'permanent-local t)
  157.  
  158. (defvar buffer-file-numbers-unique (not (memq system-type '(windows-nt)))
  159.   "Non-nil means that buffer-file-number uniquely identifies files.")
  160.  
  161. (defcustom file-precious-flag nil
  162.   "*Non-nil means protect against I/O errors while saving files.
  163. Some modes set this non-nil in particular buffers.
  164.  
  165. This feature works by writing the new contents into a temporary file
  166. and then renaming the temporary file to replace the original.
  167. In this way, any I/O error in writing leaves the original untouched,
  168. and there is never any instant where the file is nonexistent.
  169.  
  170. Note that this feature forces backups to be made by copying.
  171. Yet, at the same time, saving a precious file
  172. breaks any hard links between it and other files."
  173.   :type 'boolean
  174.   :group 'backup)
  175.  
  176. (defcustom version-control nil
  177.   "*Control use of version numbers for backup files.
  178. t means make numeric backup versions unconditionally.
  179. nil means make them for files that have some already.
  180. `never' means do not make them."
  181.   :type 'boolean
  182.   :group 'backup
  183.   :group 'vc)
  184.  
  185. ;; This is now defined in efs.
  186. ;(defvar dired-kept-versions 2
  187. ;  "*When cleaning directory, number of versions to keep.")
  188.  
  189. (defcustom delete-old-versions nil
  190.   "*If t, delete excess backup versions silently.
  191. If nil, ask confirmation.  Any other value prevents any trimming."
  192.   :type '(choice (const :tag "Delete" t)
  193.                  (const :tag "Ask" nil)
  194.                  (sexp :tag "Leave" :format "%t\n" other))
  195.   :group 'backup)
  196.  
  197. (defcustom kept-old-versions 2
  198.   "*Number of oldest versions to keep when a new numbered backup is made."
  199.   :type 'integer
  200.   :group 'backup)
  201.  
  202. (defcustom kept-new-versions 2
  203.   "*Number of newest versions to keep when a new numbered backup is made.
  204. Includes the new backup.  Must be > 0"
  205.   :type 'integer
  206.   :group 'backup)
  207.  
  208. (defcustom require-final-newline nil
  209.   "*Value of t says silently ensure a file ends in a newline when it is saved.
  210. Non-nil but not t says ask user whether to add a newline when there isn't one.
  211. nil means don't add newlines."
  212.   :type '(choice (const :tag "Off" nil)
  213.          (const :tag "Add" t)
  214.          (sexp :tag "Ask" :format "%t\n" ask))
  215.   :group 'editing-basics)
  216.  
  217. (defcustom auto-save-default t
  218.   "*Non-nil says by default do auto-saving of every file-visiting buffer."
  219.   :type 'boolean
  220.   :group 'auto-save)
  221.  
  222. (defcustom auto-save-visited-file-name nil
  223.   "*Non-nil says auto-save a buffer in the file it is visiting, when practical.
  224. Normally auto-save files are written under other names."
  225.   :type 'boolean
  226.   :group 'auto-save)
  227.  
  228. (defcustom save-abbrevs nil
  229.   "*Non-nil means save word abbrevs too when files are saved.
  230. Loading an abbrev file sets this to t."
  231.   :type 'boolean
  232.   :group 'abbrev)
  233.  
  234. (defcustom find-file-run-dired t
  235.   "*Non-nil says run dired if `find-file' is given the name of a directory."
  236.   :type 'boolean
  237.   :group 'find-file)
  238.  
  239. ;;;It is not useful to make this a local variable.
  240. ;;;(put 'find-file-not-found-hooks 'permanent-local t)
  241. (defvar find-file-not-found-hooks nil
  242.   "List of functions to be called for `find-file' on nonexistent file.
  243. These functions are called as soon as the error is detected.
  244. `buffer-file-name' is already set up.
  245. The functions are called in the order given until one of them returns non-nil.")
  246.  
  247. ;;;It is not useful to make this a local variable.
  248. ;;;(put 'find-file-hooks 'permanent-local t)
  249. (defvar find-file-hooks nil
  250.   "List of functions to be called after a buffer is loaded from a file.
  251. The buffer's local variables (if any) will have been processed before the
  252. functions are called.")
  253.  
  254. (defvar write-file-hooks nil
  255.   "List of functions to be called before writing out a buffer to a file.
  256. If one of them returns non-nil, the file is considered already written
  257. and the rest are not called.
  258. These hooks are considered to pertain to the visited file.
  259. So this list is cleared if you change the visited file name.
  260. See also `write-contents-hooks' and `continue-save-buffer'.")
  261. ;;; However, in case someone does make it local...
  262. (put 'write-file-hooks 'permanent-local t)
  263.  
  264. (defvar local-write-file-hooks nil
  265.   "Just like `write-file-hooks', except intended for per-buffer use.
  266. The functions in this list are called before the ones in
  267. `write-file-hooks'.
  268.  
  269. This variable is meant to be used for hooks that have to do with a
  270. particular visited file.  Therefore, it is a permanent local, so that
  271. changing the major mode does not clear it.  However, calling
  272. `set-visited-file-name' does clear it.")
  273. (make-variable-buffer-local 'local-write-file-hooks)
  274. (put 'local-write-file-hooks 'permanent-local t)
  275.  
  276.  
  277. ;; #### think about this (added by Sun).
  278. (put 'after-set-visited-file-name-hooks 'permanent-local t)
  279. (defvar after-set-visited-file-name-hooks nil
  280.   "List of functions to be called after \\[set-visited-file-name]
  281. or during \\[write-file].
  282. You can use this hook to restore local values of write-file-hooks,
  283. after-save-hook, and revert-buffer-function, which pertain
  284. to a specific file and therefore are normally killed by a rename.
  285. Put hooks pertaining to the buffer contents on write-contents-hooks
  286. and revert-buffer-insert-file-contents-function.")
  287.  
  288. (defvar write-contents-hooks nil
  289.   "List of functions to be called before writing out a buffer to a file.
  290. If one of them returns non-nil, the file is considered already written
  291. and the rest are not called.
  292. These hooks are considered to pertain to the buffer's contents,
  293. not to the particular visited file; thus, `set-visited-file-name' does
  294. not clear this variable, but changing the major mode does clear it.
  295. See also `write-file-hooks' and `continue-save-buffer'.")
  296.  
  297. ;;  XEmacs addition
  298. ;;  Energize needed this to hook into save-buffer at a lower level; we need
  299. ;;  to provide a new output method, but don't want to have to duplicate all
  300. ;;  of the backup file and file modes logic.that does not occur if one uses
  301. ;;  a write-file-hook which returns non-nil.
  302. (put 'write-file-data-hooks 'permanent-local t)
  303. (defvar write-file-data-hooks nil
  304.   "List of functions to be called to put the bytes on disk.  
  305. These functions receive the name of the file to write to as argument.
  306. The default behavior is to call 
  307.   (write-region (point-min) (point-max) filename nil t)
  308. If one of them returns non-nil, the file is considered already written
  309. and the rest are not called.
  310. These hooks are considered to pertain to the visited file.
  311. So this list is cleared if you change the visited file name.
  312. See also `write-file-hooks'.")
  313.  
  314. (defcustom enable-local-variables t
  315.   "*Control use of local-variables lists in files you visit.
  316. The value can be t, nil or something else.
  317. A value of t means local-variables lists are obeyed;
  318. nil means they are ignored; anything else means query.
  319.  
  320. The command \\[normal-mode] always obeys local-variables lists
  321. and ignores this variable."
  322.   :type '(choice (const :tag "Obey" t)
  323.          (const :tag "Ignore" nil)
  324.          (sexp :tag "Query" :format "%t\n" other))
  325.   :group 'find-file)
  326.  
  327. (defcustom enable-local-eval 'maybe
  328.   "*Control processing of the \"variable\" `eval' in a file's local variables.
  329. The value can be t, nil or something else.
  330. A value of t means obey `eval' variables;
  331. nil means ignore them; anything else means query.
  332.  
  333. The command \\[normal-mode] always obeys local-variables lists
  334. and ignores this variable."
  335.   :type '(choice (const :tag "Obey" t)
  336.          (const :tag "Ignore" nil)
  337.          (sexp :tag "Query" :format "%t\n" other))
  338.   :group 'find-file)
  339.  
  340. ;; Avoid losing in versions where CLASH_DETECTION is disabled.
  341. (or (fboundp 'lock-buffer)
  342.     (defalias 'lock-buffer 'ignore))
  343. (or (fboundp 'unlock-buffer)
  344.     (defalias 'unlock-buffer 'ignore))
  345.  
  346. ;;FSFmacs bastardized ange-ftp cruft
  347. ;; This hook function provides support for ange-ftp host name
  348. ;; completion.  It runs the usual ange-ftp hook, but only for
  349. ;; completion operations.  Having this here avoids the need
  350. ;; to load ange-ftp when it's not really in use.
  351. ;(defun ange-ftp-completion-hook-function (op &rest args)
  352. ;  (if (memq op '(file-name-completion file-name-all-completions))
  353. ;      (apply 'ange-ftp-hook-function op args)
  354. ;    (let ((inhibit-file-name-handlers
  355. ;       (cons 'ange-ftp-completion-hook-function
  356. ;         (and (eq inhibit-file-name-operation op)
  357. ;              inhibit-file-name-handlers)))
  358. ;      (inhibit-file-name-operation op))
  359. ;      (apply op args))
  360.  
  361. (defun convert-standard-filename (filename)
  362.   "Convert a standard file's name to something suitable for the current OS.
  363. This function's standard definition is trivial; it just returns the argument.
  364. However, on some systems, the function is redefined
  365. with a definition that really does change some file names."
  366.   filename)
  367.  
  368. (defun pwd ()
  369.   "Show the current default directory."
  370.   (interactive nil)
  371.   (message "Directory %s" default-directory))
  372.  
  373. (defvar cd-path nil
  374.   "Value of the CDPATH environment variable, as a list.
  375. Not actually set up until the first time you use it.")
  376.  
  377. (defvar path-separator ":"
  378.   "Character used to separate concatenated paths.")
  379.  
  380. (defun parse-colon-path (cd-path)
  381.   "Explode a colon-separated list of paths into a string list."
  382.   (and cd-path
  383.        (let (cd-list (cd-start 0) cd-colon)
  384.      (setq cd-path (concat cd-path path-separator))
  385.      (while (setq cd-colon (string-match path-separator cd-path cd-start))
  386.        (setq cd-list
  387.          (nconc cd-list
  388.             (list (if (= cd-start cd-colon)
  389.                    nil
  390.                 (substitute-in-file-name
  391.                  (file-name-as-directory
  392.                   (substring cd-path cd-start cd-colon)))))))
  393.        (setq cd-start (+ cd-colon 1)))
  394.      cd-list)))
  395.  
  396. (defun cd-absolute (dir)
  397.   "Change current directory to given absolute file name DIR."
  398.   ;; Put the name into directory syntax now,
  399.   ;; because otherwise expand-file-name may give some bad results.
  400.   (if (not (eq system-type 'vax-vms))
  401.       (setq dir (file-name-as-directory dir)))
  402.   ;; XEmacs change: stig@hackvan.com
  403.   (if find-file-use-truenames
  404.       (setq dir (file-truename dir)))
  405.   (setq dir (abbreviate-file-name (expand-file-name dir)))
  406.   (cond ((not (file-directory-p dir))
  407.          (error "%s is not a directory" dir))
  408.     ;; this breaks ange-ftp, which doesn't (can't?) overload `file-executable-p'.
  409.         ;;((not (file-executable-p dir))
  410.         ;; (error "Cannot cd to %s:  Permission denied" dir))
  411.         (t
  412.          (setq default-directory dir))))
  413.  
  414. (defun cd (dir)
  415.   "Make DIR become the current buffer's default directory.
  416. If your environment includes a `CDPATH' variable, try each one of that
  417. colon-separated list of directories when resolving a relative directory name."
  418.   (interactive
  419.    ;; XEmacs change? (read-file-name => read-directory-name)
  420.    (list (read-directory-name "Change default directory: "
  421.                   default-directory default-directory
  422.                   (and (member cd-path '(nil ("./")))
  423.                    (null (getenv "CDPATH"))))))
  424.   (if (file-name-absolute-p dir)
  425.       (cd-absolute (expand-file-name dir))
  426.     ;; XEmacs
  427.     (if (null cd-path)
  428.     ;;#### Unix-specific
  429.     (let ((trypath (parse-colon-path (getenv "CDPATH"))))
  430.       (setq cd-path (or trypath (list "./")))))
  431.     (or (catch 'found
  432.       (mapcar #'(lambda (x)
  433.                 (let ((f (expand-file-name (concat x dir))))
  434.               (if (file-directory-p f)
  435.                   (progn
  436.                     (cd-absolute f)
  437.                     (throw 'found t)))))
  438.           cd-path)
  439.       nil)
  440.     ;; jwz: give a better error message to those of us with the
  441.     ;; good taste not to use a kludge like $CDPATH.
  442.     (if (equal cd-path '("./"))
  443.         (error "No such directory: %s" (expand-file-name dir))
  444.       (error "Directory not found in $CDPATH: %s" dir)))))
  445.  
  446. (defun load-file (file)
  447.   "Load the Lisp file named FILE."
  448.   (interactive "fLoad file: ")
  449.   (load (expand-file-name file) nil nil t))
  450.  
  451. ; We now dump utils/lib-complete.el which has improved versions of this.
  452. ;(defun load-library (library)
  453. ;  "Load the library named LIBRARY.
  454. ;This is an interface to the function `load'."
  455. ;  (interactive "sLoad library: ")
  456. ;  (load library))
  457. ;
  458. ;(defun find-library (library)
  459. ;  "Find the library of Lisp code named LIBRARY.
  460. ;This searches `load-path' for a file named either \"LIBRARY\" or \"LIBRARY.el\"."
  461. ;  (interactive "sFind library file: ")
  462. ;  (let ((f (locate-file library load-path ":.el:")))
  463. ;    (if f
  464. ;        (find-file f)
  465. ;        (error "Couldn't locate library %s" library))))
  466.  
  467. (defun file-local-copy (file &optional buffer)
  468.   "Copy the file FILE into a temporary file on this machine.
  469. Returns the name of the local copy, or nil, if FILE is directly
  470. accessible."
  471.   (let ((handler (find-file-name-handler file 'file-local-copy)))
  472.     (if handler
  473.     (funcall handler 'file-local-copy file)
  474.       nil)))
  475.  
  476. ;; XEmacs change block
  477. ; We have this in C and use the realpath() system call.
  478.  
  479. ;(defun file-truename (filename &optional counter prev-dirs)
  480. ;  "Return the truename of FILENAME, which should be absolute.
  481. ;The truename of a file name is found by chasing symbolic links
  482. ;both at the level of the file and at the level of the directories
  483. ;containing it, until no links are left at any level.
  484. ;
  485. ;The arguments COUNTER and PREV-DIRS are used only in recursive calls.
  486. ;Do not specify them in other calls."
  487. ;  ;; COUNTER can be a cons cell whose car is the count of how many more links
  488. ;  ;; to chase before getting an error.
  489. ;  ;; PREV-DIRS can be a cons cell whose car is an alist
  490. ;  ;; of truenames we've just recently computed.
  491. ;  ;; The last test looks dubious, maybe `+' is meant here?  --simon.
  492. ;  (if (or (string= filename "") (string= filename "~")
  493. ;      (and (string= (substring filename 0 1) "~")
  494. ;           (string-match "~[^/]*" filename)))
  495. ;      (progn
  496. ;    (setq filename (expand-file-name filename))
  497. ;    (if (string= filename "")
  498. ;        (setq filename "/"))))
  499. ;  (or counter (setq counter (list 100)))
  500. ;  (let (done
  501. ;    ;; For speed, remove the ange-ftp completion handler from the list.
  502. ;    ;; We know it's not needed here.
  503. ;    ;; For even more speed, do this only on the outermost call.
  504. ;    (file-name-handler-alist
  505. ;     (if prev-dirs file-name-handler-alist
  506. ;       (let ((tem (copy-sequence file-name-handler-alist)))
  507. ;         (delq (rassq 'ange-ftp-completion-hook-function tem) tem)))))
  508. ;    (or prev-dirs (setq prev-dirs (list nil)))
  509. ;    ;; If this file directly leads to a link, process that iteratively
  510. ;    ;; so that we don't use lots of stack.
  511. ;    (while (not done)
  512. ;      (setcar counter (1- (car counter)))
  513. ;      (if (< (car counter) 0)
  514. ;      (error "Apparent cycle of symbolic links for %s" filename))
  515. ;      (let ((handler (find-file-name-handler filename 'file-truename)))
  516. ;    ;; For file name that has a special handler, call handler.
  517. ;    ;; This is so that ange-ftp can save time by doing a no-op.
  518. ;    (if handler
  519. ;        (setq filename (funcall handler 'file-truename filename)
  520. ;          done t)
  521. ;      (let ((dir (or (file-name-directory filename) default-directory))
  522. ;        target dirfile)
  523. ;        ;; Get the truename of the directory.
  524. ;        (setq dirfile (directory-file-name dir))
  525. ;        ;; If these are equal, we have the (or a) root directory.
  526. ;        (or (string= dir dirfile)
  527. ;        ;; If this is the same dir we last got the truename for,
  528. ;        ;; save time--don't recalculate.
  529. ;        (if (assoc dir (car prev-dirs))
  530. ;            (setq dir (cdr (assoc dir (car prev-dirs))))
  531. ;          (let ((old dir)
  532. ;            (new (file-name-as-directory (file-truename dirfile counter prev-dirs))))
  533. ;            (setcar prev-dirs (cons (cons old new) (car prev-dirs)))
  534. ;            (setq dir new))))
  535. ;        (if (equal ".." (file-name-nondirectory filename))
  536. ;        (setq filename
  537. ;              (directory-file-name (file-name-directory (directory-file-name dir)))
  538. ;              done t)
  539. ;          (if (equal "." (file-name-nondirectory filename))
  540. ;          (setq filename (directory-file-name dir)
  541. ;            done t)
  542. ;        ;; Put it back on the file name.
  543. ;        (setq filename (concat dir (file-name-nondirectory filename)))
  544. ;        ;; Is the file name the name of a link?
  545. ;        (setq target (file-symlink-p filename))
  546. ;        (if target
  547. ;            ;; Yes => chase that link, then start all over
  548. ;            ;; since the link may point to a directory name that uses links.
  549. ;            ;; We can't safely use expand-file-name here
  550. ;            ;; since target might look like foo/../bar where foo
  551. ;            ;; is itself a link.  Instead, we handle . and .. above.
  552. ;            (setq filename
  553. ;              (if (file-name-absolute-p target)
  554. ;                  target
  555. ;                (concat dir target))
  556. ;              done nil)
  557. ;          ;; No, we are done!
  558. ;          (setq done t))))))))
  559. ;    filename))
  560.  
  561. ;; XEmacs addition.  Called from `insert-file-contents-internal'
  562. ;; at the appropriate time.
  563. (defun compute-buffer-file-truename (&optional buffer)
  564.   "Recomputes BUFFER's value of `buffer-file-truename'
  565. based on the current value of `buffer-file-name'.
  566. BUFFER defaults to the current buffer if unspecified."
  567.   (save-excursion
  568.     (set-buffer (or buffer (current-buffer)))
  569.     (cond ((null buffer-file-name)
  570.        (setq buffer-file-truename nil))
  571.       ((setq buffer-file-truename (file-truename buffer-file-name))
  572.        ;; it exists, we're done.
  573.        nil)
  574.       (t
  575.        ;; the file doesn't exist, but maybe the directory does.
  576.        (let* ((dir (file-name-directory buffer-file-name))
  577.           (truedir (file-truename dir)))
  578.          (if truedir (setq dir truedir))
  579.          (setq buffer-file-truename
  580.            (expand-file-name (file-name-nondirectory buffer-file-name)
  581.                      dir)))))
  582.     (if (and find-file-use-truenames buffer-file-truename)
  583.     (setq buffer-file-name (abbreviate-file-name buffer-file-truename)
  584.           default-directory (file-name-directory buffer-file-name)))
  585.     buffer-file-truename))
  586. ;; End XEmacs change block
  587.  
  588. (defun file-chase-links (filename)
  589.   "Chase links in FILENAME until a name that is not a link.
  590. Does not examine containing directories for links,
  591. unlike `file-truename'."
  592.   (let (tem (count 100) (newname filename))
  593.     (while (setq tem (file-symlink-p newname))
  594.       (if (= count 0)
  595.       (error "Apparent cycle of symbolic links for %s" filename))
  596.       ;; In the context of a link, `//' doesn't mean what XEmacs thinks.
  597.       (while (string-match "//+" tem)
  598.     (setq tem (concat (substring tem 0 (1+ (match-beginning 0)))
  599.               (substring tem (match-end 0)))))
  600.       ;; Handle `..' by hand, since it needs to work in the
  601.       ;; target of any directory symlink.
  602.       ;; This code is not quite complete; it does not handle
  603.       ;; embedded .. in some cases such as ./../foo and foo/bar/../../../lose.
  604.       (while (string-match "\\`\\.\\./" tem) ;#### Unix specific
  605.     (setq tem (substring tem 3))
  606.     (setq newname (file-name-as-directory
  607.                ;; Do the .. by hand.
  608.                (directory-file-name
  609.             (file-name-directory
  610.              ;; Chase links in the default dir of the symlink.
  611.              (file-chase-links
  612.               (directory-file-name
  613.                (file-name-directory newname))))))))
  614.       (setq newname (expand-file-name tem (file-name-directory newname)))
  615.       (setq count (1- count)))
  616.     newname))
  617.  
  618. (defun switch-to-other-buffer (arg)
  619.   "Switch to the previous buffer.  With a numeric arg, n, switch to the nth
  620. most recent buffer.  With an arg of 0, buries the current buffer at the
  621. bottom of the buffer stack."
  622.   (interactive "p")
  623.   (if (eq arg 0)
  624.       (bury-buffer (current-buffer)))
  625.   (switch-to-buffer
  626.    (if (<= arg 1) (other-buffer (current-buffer))
  627.      (nth (1+ arg) (buffer-list)))))
  628.  
  629. (defun switch-to-buffer-other-window (buffer)
  630.   "Select buffer BUFFER in another window."
  631.   (interactive "BSwitch to buffer in other window: ")
  632.   (let ((pop-up-windows t))
  633.     ;; XEmacs: this used to have (selected-frame) as the third argument,
  634.     ;; but this is obnoxious.  If the user wants the buffer in a
  635.     ;; different frame, then it should be this way.
  636.  
  637.     ;; Change documented above undone --mrb
  638.     (pop-to-buffer buffer t (selected-frame))))
  639.  
  640. (defun switch-to-buffer-other-frame (buffer)
  641.   "Switch to buffer BUFFER in a newly-created frame."
  642.   (interactive "BSwitch to buffer in other frame: ")
  643.   (let* ((name (get-frame-name-for-buffer buffer))
  644.      (frame (make-frame (if name
  645.                   (list (cons 'name (symbol-name name)))))))
  646.     (pop-to-buffer buffer t frame)
  647.     (make-frame-visible frame)
  648.     buffer))
  649.  
  650. (defun find-file (filename &optional codesys)
  651.   "Edit file FILENAME.
  652. Switch to a buffer visiting file FILENAME,
  653. creating one if none already exists.
  654. Under XEmacs/Mule, optional second argument specifies the
  655. coding system to use when decoding the file.  Interactively,
  656. with a prefix argument, you will be prompted for the coding system."
  657.   (interactive "FFind file: \nZCoding system: ")
  658.   (if codesys
  659.       (let ((coding-system-for-read
  660.          (get-coding-system codesys)))
  661.     (switch-to-buffer (find-file-noselect filename)))
  662.     (switch-to-buffer (find-file-noselect filename))))
  663.  
  664. (defun find-file-other-window (filename &optional codesys)
  665.   "Edit file FILENAME, in another window.
  666. May create a new window, or reuse an existing one.
  667. See the function `display-buffer'.
  668. Under XEmacs/Mule, optional second argument specifies the
  669. coding system to use when decoding the file.  Interactively,
  670. with a prefix argument, you will be prompted for the coding system."
  671.   (interactive "FFind file in other window: \nZCoding system: ")
  672.   (if codesys
  673.       (let ((coding-system-for-read
  674.          (get-coding-system codesys)))
  675.     (switch-to-buffer-other-window (find-file-noselect filename)))
  676.     (switch-to-buffer-other-window (find-file-noselect filename))))
  677.  
  678. (defun find-file-other-frame (filename &optional codesys)
  679.   "Edit file FILENAME, in a newly-created frame.
  680. Under XEmacs/Mule, optional second argument specifies the
  681. coding system to use when decoding the file.  Interactively,
  682. with a prefix argument, you will be prompted for the coding system."
  683.   (interactive "FFind file in other frame: \nZCoding system: ")
  684.   (if codesys
  685.       (let ((coding-system-for-read
  686.          (get-coding-system codesys)))
  687.     (switch-to-buffer-other-frame (find-file-noselect filename)))
  688.     (switch-to-buffer-other-frame (find-file-noselect filename))))
  689.  
  690. (defun find-file-read-only (filename &optional codesys)
  691.   "Edit file FILENAME but don't allow changes.
  692. Like \\[find-file] but marks buffer as read-only.
  693. Use \\[toggle-read-only] to permit editing.
  694. Under XEmacs/Mule, optional second argument specifies the
  695. coding system to use when decoding the file.  Interactively,
  696. with a prefix argument, you will be prompted for the coding system."
  697.   (interactive "fFind file read-only: \nZCoding system: ")
  698.   (if codesys
  699.       (let ((coding-system-for-read
  700.          (get-coding-system codesys)))
  701.     (find-file filename))
  702.     (find-file filename))
  703.   (setq buffer-read-only t)
  704.   (current-buffer))
  705.  
  706. (defun find-file-read-only-other-window (filename &optional codesys)
  707.   "Edit file FILENAME in another window but don't allow changes.
  708. Like \\[find-file-other-window] but marks buffer as read-only.
  709. Use \\[toggle-read-only] to permit editing.
  710. Under XEmacs/Mule, optional second argument specifies the
  711. coding system to use when decoding the file.  Interactively,
  712. with a prefix argument, you will be prompted for the coding system."
  713.   (interactive "fFind file read-only other window: \nZCoding system: ")
  714.   (if codesys
  715.       (let ((coding-system-for-read
  716.          (get-coding-system codesys)))
  717.     (find-file-other-window filename))
  718.     (find-file-other-window filename))
  719.   (setq buffer-read-only t)
  720.   (current-buffer))
  721.  
  722. (defun find-file-read-only-other-frame (filename &optional codesys)
  723.   "Edit file FILENAME in another frame but don't allow changes.
  724. Like \\[find-file-other-frame] but marks buffer as read-only.
  725. Use \\[toggle-read-only] to permit editing.
  726. Under XEmacs/Mule, optional second argument specifies the
  727. coding system to use when decoding the file.  Interactively,
  728. with a prefix argument, you will be prompted for the coding system."
  729.   (interactive "fFind file read-only other frame: \nZCoding system: ")
  730.   (if codesys
  731.       (let ((coding-system-for-read
  732.          (get-coding-system codesys)))
  733.     (find-file-other-frame filename))
  734.     (find-file-other-frame filename))
  735.   (setq buffer-read-only t)
  736.   (current-buffer))
  737.  
  738. (defun find-alternate-file-other-window (filename &optional codesys)
  739.   "Find file FILENAME as a replacement for the file in the next window.
  740. This command does not select that window.
  741. Under XEmacs/Mule, optional second argument specifies the
  742. coding system to use when decoding the file.  Interactively,
  743. with a prefix argument, you will be prompted for the coding system."
  744.   (interactive
  745.    (save-selected-window
  746.      (other-window 1)
  747.      (let ((file buffer-file-name)
  748.        (file-name nil)
  749.        (file-dir nil))
  750.        (and file
  751.         (setq file-name (file-name-nondirectory file)
  752.           file-dir (file-name-directory file)))
  753.        (list (read-file-name
  754.           "Find alternate file: " file-dir nil nil file-name)
  755.          (if (and current-prefix-arg (featurep 'mule))
  756.          (read-coding-system "Coding-system: "))))))
  757.   (if (one-window-p)
  758.       (find-file-other-window filename)
  759.     (save-selected-window
  760.       (other-window 1)
  761.       (find-alternate-file filename codesys))))
  762.  
  763. (defun find-alternate-file (filename &optional codesys)
  764.   "Find file FILENAME, select its buffer, kill previous buffer.
  765. If the current buffer now contains an empty file that you just visited
  766. \(presumably by mistake), use this command to visit the file you really want.
  767. Under XEmacs/Mule, optional second argument specifies the
  768. coding system to use when decoding the file.  Interactively,
  769. with a prefix argument, you will be prompted for the coding system."
  770.   (interactive
  771.    (let ((file buffer-file-name)
  772.      (file-name nil)
  773.      (file-dir nil))
  774.      (and file
  775.       (setq file-name (file-name-nondirectory file)
  776.         file-dir (file-name-directory file)))
  777.      (list (read-file-name
  778.         "Find alternate file: " file-dir nil nil file-name)
  779.        (if (and current-prefix-arg (featurep 'mule))
  780.            (read-coding-system "Coding-system: ")))))
  781.   (and (buffer-modified-p) (buffer-file-name)
  782.        ;; (not buffer-read-only)
  783.        (not (yes-or-no-p (format
  784.               "Buffer %s is modified; kill anyway? "
  785.               (buffer-name))))
  786.        (error "Aborted"))
  787.   (let ((obuf (current-buffer))
  788.     (ofile buffer-file-name)
  789.     (onum buffer-file-number)
  790.     (otrue buffer-file-truename)
  791.     (oname (buffer-name)))
  792.     (if (get-buffer " **lose**")
  793.     (kill-buffer " **lose**"))
  794.     (rename-buffer " **lose**")
  795.     (setq buffer-file-name nil)
  796.     (setq buffer-file-number nil)
  797.     (setq buffer-file-truename nil)
  798.     (unwind-protect
  799.     (progn
  800.       (unlock-buffer)
  801.       (if codesys
  802.           (let ((coding-system-for-read
  803.              (get-coding-system codesys)))
  804.         (find-file filename))
  805.         (find-file filename)))
  806.       (cond ((eq obuf (current-buffer))
  807.          (setq buffer-file-name ofile)
  808.          (setq buffer-file-number onum)
  809.          (setq buffer-file-truename otrue)
  810.          (lock-buffer)
  811.          (rename-buffer oname))))
  812.     (or (eq (current-buffer) obuf)
  813.     (kill-buffer obuf))))
  814.  
  815. (defun create-file-buffer (filename)
  816.   "Create a suitably named buffer for visiting FILENAME, and return it.
  817. FILENAME (sans directory) is used unchanged if that name is free;
  818. otherwise a string <2> or <3> or ... is appended to get an unused name."
  819.     (let ((handler (find-file-name-handler filename 'create-file-buffer)))
  820.       (if handler
  821.       (funcall handler 'create-file-buffer filename)
  822.     (let ((lastname (file-name-nondirectory filename)))
  823.       (if (string= lastname "")
  824.           (setq lastname filename))
  825.       (generate-new-buffer lastname)))))
  826.  
  827. (defun generate-new-buffer (name)
  828.   "Create and return a buffer with a name based on NAME.
  829. Choose the buffer's name using `generate-new-buffer-name'."
  830.   (get-buffer-create (generate-new-buffer-name name)))
  831.  
  832. (defvar abbreviated-home-dir nil
  833.   "The user's homedir abbreviated according to `directory-abbrev-alist'.")
  834.  
  835. (defun abbreviate-file-name (filename &optional hack-homedir)
  836.   "Return a version of FILENAME shortened using `directory-abbrev-alist'.
  837. See documentation of variable `directory-abbrev-alist' for more information.
  838. If optional argument HACK-HOMEDIR is non-nil, then this also substitutes
  839. \"~\" for the user's home directory."
  840.   (let ((handler (find-file-name-handler filename 'abbreviate-file-name)))
  841.     (if handler
  842.     (funcall handler 'abbreviate-file-name filename hack-homedir)
  843.       ;; Get rid of the prefixes added by the automounter.
  844.       ;;(if (and (string-match automount-dir-prefix filename)
  845.       ;;         (file-exists-p (file-name-directory
  846.       ;;                         (substring filename (1- (match-end 0))))))
  847.       ;;    (setq filename (substring filename (1- (match-end 0)))))
  848.       (let ((tail directory-abbrev-alist))
  849.     ;; If any elt of directory-abbrev-alist matches this name,
  850.     ;; abbreviate accordingly.
  851.     (while tail
  852.       (if (string-match (car (car tail)) filename)
  853.           (setq filename
  854.             (concat (cdr (car tail)) (substring filename (match-end 0)))))
  855.       (setq tail (cdr tail))))
  856.       (if hack-homedir
  857.       (progn
  858.         ;; Compute and save the abbreviated homedir name.
  859.         ;; We defer computing this until the first time it's needed, to
  860.         ;; give time for directory-abbrev-alist to be set properly.
  861.         ;; We include a slash at the end, to avoid spurious matches
  862.         ;; such as `/usr/foobar' when the home dir is `/usr/foo'.
  863.         (or abbreviated-home-dir
  864.         (setq abbreviated-home-dir
  865.               (let ((abbreviated-home-dir "$foo"))
  866.             (concat "\\`" (regexp-quote (abbreviate-file-name
  867.                              (expand-file-name "~")))
  868.                 "\\(/\\|\\'\\)"))))
  869.         ;; If FILENAME starts with the abbreviated homedir,
  870.         ;; make it start with `~' instead.
  871.         (if (and (string-match abbreviated-home-dir filename)
  872.              ;; If the home dir is just /, don't change it.
  873.              (not (and (= (match-end 0) 1) ;#### unix-specific
  874.                    (= (aref filename 0) ?/)))
  875.              (not (and (or (eq system-type 'ms-dos) 
  876.                    (eq system-type 'windows-nt))
  877.                    (save-match-data
  878.                  (string-match "^[a-zA-Z]:/$" filename)))))
  879.         (setq filename
  880.               (concat "~"
  881.                   (substring filename
  882.                      (match-beginning 1) (match-end 1))
  883.                   (substring filename (match-end 0)))))))
  884.       filename)))
  885.  
  886. (defcustom find-file-not-true-dirname-list nil
  887.   "*List of logical names for which visiting shouldn't save the true dirname.
  888. On VMS, when you visit a file using a logical name that searches a path,
  889. you may or may not want the visited file name to record the specific
  890. directory where the file was found.  If you *do not* want that, add the logical
  891. name to this list as a string."
  892.   :type '(repeat (string :tag "Name"))
  893.   :group 'find-file)
  894.  
  895. ;; This function is needed by FSF vc.el.  I hope somebody can make it
  896. ;; work for XEmacs.  -sb.
  897. (defun find-buffer-visiting (filename)
  898.   "Return the buffer visiting file FILENAME (a string).
  899. This is like `get-file-buffer', except that it checks for any buffer
  900. visiting the same file, possibly under a different name.
  901. If there is no such live buffer, return nil."
  902.   (let ((buf (get-file-buffer filename))
  903.     (truename (abbreviate-file-name (file-truename filename))))
  904.     (or buf
  905.     (let ((list (buffer-list)) found)
  906.       (while (and (not found) list)
  907.         (save-excursion
  908.           (set-buffer (car list))
  909.           (if (and buffer-file-name
  910.                (string= buffer-file-truename truename))
  911.           (setq found (car list))))
  912.         (setq list (cdr list)))
  913.       found)
  914.     (let ((number (nthcdr 10 (file-attributes truename)))
  915.           (list (buffer-list)) found)
  916.       (and buffer-file-numbers-unique
  917.            number
  918.            (while (and (not found) list)
  919.          (save-excursion
  920.            (set-buffer (car list))
  921.            (if (and buffer-file-number
  922.                            (equal buffer-file-number number)
  923.                 ;; Verify this buffer's file number
  924.                 ;; still belongs to its file.
  925.                 (file-exists-p buffer-file-name)
  926.                 (equal (nthcdr 10 (file-attributes buffer-file-name))
  927.                    number))
  928.                (setq found (car list))))
  929.          (setq list (cdr list))))
  930.       found))))
  931.  
  932. (defun insert-file-contents-literally (filename &optional visit beg end replace)
  933.   "Like `insert-file-contents', q.v., but only reads in the file.
  934. A buffer may be modified in several ways after reading into the buffer due
  935. to advanced Emacs features, such as file-name-handlers, format decoding,
  936. find-file-hooks, etc.
  937.   This function ensures that none of these modifications will take place."
  938.   (let ((file-name-handler-alist nil)
  939.     (format-alist nil)
  940.     (after-insert-file-functions nil)
  941.     (find-buffer-file-type-function 
  942.      (if (fboundp 'find-buffer-file-type)
  943.          (symbol-function 'find-buffer-file-type)
  944.        nil)))
  945.     (unwind-protect
  946.     (progn
  947.       (fset 'find-buffer-file-type (lambda (filename) t))
  948.       (insert-file-contents filename visit beg end replace))
  949.       (if find-buffer-file-type-function
  950.       (fset 'find-buffer-file-type find-buffer-file-type-function)
  951.     (fmakunbound 'find-buffer-file-type)))))
  952.  
  953. (defun find-file-noselect (filename &optional nowarn rawfile)
  954.   "Read file FILENAME into a buffer and return the buffer.
  955. If a buffer exists visiting FILENAME, return that one, but
  956. verify that the file has not changed since visited or saved.
  957. The buffer is not selected, just returned to the caller.
  958. If NOWARN is non-nil, warning messages about several potential
  959. problems will be suppressed."
  960.   (setq filename (abbreviate-file-name (expand-file-name filename)))
  961.   (if (file-directory-p filename)
  962.       (if find-file-run-dired
  963.       (dired-noselect (if find-file-use-truenames
  964.                   (abbreviate-file-name (file-truename filename))
  965.                 filename))
  966.     (error "%s is a directory." filename))
  967.     (let* ((buf (get-file-buffer filename))
  968. ;       (truename (abbreviate-file-name (file-truename filename)))
  969.        (number (nthcdr 10 (file-attributes (file-truename filename))))
  970. ;       (number (and buffer-file-truename
  971. ;            (nthcdr 10 (file-attributes buffer-file-truename))))
  972. ;       ;; Find any buffer for a file which has same truename.
  973. ;       (other (and (not buf) (find-buffer-visiting filename)))
  974.            (error nil))
  975.  
  976. ;     ;; Let user know if there is a buffer with the same truename.
  977. ;      (if (and (not buf) same-truename (not nowarn))
  978. ;      (message "%s and %s are the same file (%s)"
  979. ;           filename (buffer-file-name same-truename)
  980. ;           truename)
  981. ;    (if (and (not buf) same-number (not nowarn))
  982. ;      (message "%s and %s are the same file"
  983. ;           filename (buffer-file-name same-number))))
  984. ;      ;; Optionally also find that buffer.
  985. ;      (if (or find-file-existing-other-name find-file-visit-truename)
  986. ;      (setq buf (or same-truename same-number)))
  987.  
  988.       (when (and buf
  989.          (or find-file-compare-truenames find-file-use-truenames)
  990.          (not nowarn))
  991.     (save-excursion
  992.       (set-buffer buf)
  993.       (if (not (string-equal buffer-file-name filename))
  994.           (message "%s and %s are the same file (%s)"
  995.                filename buffer-file-name
  996.                buffer-file-truename))))
  997.  
  998.       (if buf
  999.       (or nowarn
  1000.           (verify-visited-file-modtime buf)
  1001.           (cond ((not (file-exists-p filename))
  1002.              (error "File %s no longer exists!" filename))
  1003.             ;; Certain files should be reverted automatically
  1004.             ;; if they have changed on disk and not in the buffer.
  1005.             ((and (not (buffer-modified-p buf))
  1006.               (let (found)
  1007.                 (dolist (rx revert-without-query found)
  1008.                   (when (string-match rx filename)
  1009.                 (setq found t)))))
  1010.              (with-current-buffer buf
  1011.                (message "Reverting file %s..." filename)
  1012.                (revert-buffer t t)
  1013.                (message "Reverting file %s... done" filename)))
  1014.             ((yes-or-no-p
  1015.               (if (string= (file-name-nondirectory filename)
  1016.                    (buffer-name buf))
  1017.               (format
  1018.                (if (buffer-modified-p buf)
  1019.     (gettext "File %s changed on disk.  Discard your edits? ")
  1020.     (gettext "File %s changed on disk.  Reread from disk? "))
  1021.                (file-name-nondirectory filename))
  1022.             (format
  1023.              (if (buffer-modified-p buf)
  1024.       (gettext "File %s changed on disk.  Discard your edits in %s? ")
  1025.       (gettext "File %s changed on disk.  Reread from disk into %s? "))
  1026.              (file-name-nondirectory filename)
  1027.              (buffer-name buf))))
  1028.              (save-excursion
  1029.                (set-buffer buf)
  1030.                (revert-buffer t t)))))
  1031.     ;; Else: we must create a new buffer for filename
  1032.     (save-excursion
  1033. ;;; The truename stuff makes this obsolete.
  1034. ;;;      (let* ((link-name (car (file-attributes filename)))
  1035. ;;;         (linked-buf (and (stringp link-name)
  1036. ;;;                  (get-file-buffer link-name))))
  1037. ;;;        (if (bufferp linked-buf)
  1038. ;;;        (message "Symbolic link to file in buffer %s"
  1039. ;;;             (buffer-name linked-buf))))
  1040.       (setq buf (create-file-buffer filename))
  1041.       (set-buffer-major-mode buf)
  1042.       (set-buffer buf)
  1043.       (erase-buffer)
  1044.       (if rawfile
  1045.           (condition-case ()
  1046.           (insert-file-contents-literally filename t)
  1047.         (file-error
  1048.          ;; Unconditionally set error
  1049.          (setq error t)))
  1050.         (condition-case e
  1051.         (insert-file-contents filename t)
  1052.           (file-error
  1053.            ;; Run find-file-not-found-hooks until one returns non-nil.
  1054.            (or (run-hook-with-args-until-success 'find-file-not-found-hooks)
  1055.            ;; If they fail too, set error.
  1056.            (setq error e)))))
  1057.       ;; Find the file's truename, and maybe use that as visited name.
  1058.       ;; automatically computed in XEmacs.
  1059. ;         (setq buffer-file-truename truename)
  1060.       (setq buffer-file-number number)
  1061.       ;; On VMS, we may want to remember which directory in a search list
  1062.       ;; the file was found in.
  1063.       (and (eq system-type 'vax-vms)
  1064.            (let (logical)
  1065.          (if (string-match ":" (file-name-directory filename))
  1066.              (setq logical (substring (file-name-directory filename)
  1067.                           0 (match-beginning 0))))
  1068.          (not (member logical find-file-not-true-dirname-list)))
  1069.            (setq buffer-file-name buffer-file-truename))
  1070. ;      (if find-file-visit-truename
  1071. ;          (setq buffer-file-name
  1072. ;            (setq filename
  1073. ;              (expand-file-name buffer-file-truename))))
  1074.       (and find-file-use-truenames
  1075.            ;; This should be in C.  Put pathname abbreviations that have
  1076.            ;; been explicitly requested back into the pathname.  Most
  1077.            ;; importantly, strip out automounter /tmp_mnt directories so
  1078.            ;; that auto-save will work 
  1079.            (setq buffer-file-name (abbreviate-file-name buffer-file-name)))
  1080.       ;; Set buffer's default directory to that of the file.
  1081.       (setq default-directory (file-name-directory buffer-file-name))
  1082.       ;; Turn off backup files for certain file names.  Since
  1083.       ;; this is a permanent local, the major mode won't eliminate it.
  1084.       (and (not (funcall backup-enable-predicate buffer-file-name))
  1085.            (progn
  1086.          (make-local-variable 'backup-inhibited)
  1087.          (setq backup-inhibited t)))
  1088.       (if rawfile
  1089.           nil
  1090.         (after-find-file error (not nowarn))
  1091.         (setq buf (current-buffer)))))
  1092.       buf)))
  1093.  
  1094. (defvar after-find-file-from-revert-buffer nil)
  1095.  
  1096. (defun after-find-file (&optional error warn noauto
  1097.                   after-find-file-from-revert-buffer
  1098.                   nomodes)
  1099.   "Called after finding a file and by the default revert function.
  1100. Sets buffer mode, parses local variables.
  1101. Optional args ERROR, WARN, and NOAUTO: ERROR non-nil means there was an
  1102. error in reading the file.  WARN non-nil means warn if there
  1103. exists an auto-save file more recent than the visited file.
  1104. NOAUTO means don't mess with auto-save mode.
  1105. Fourth arg AFTER-FIND-FILE-FROM-REVERT-BUFFER non-nil
  1106.  means this call was from `revert-buffer'.
  1107. Fifth arg NOMODES non-nil means don't alter the file's modes.
  1108. Finishes by calling the functions in `find-file-hooks'."
  1109.   (setq buffer-read-only (not (file-writable-p buffer-file-name)))
  1110.   (if noninteractive
  1111.       nil
  1112.     (let* (not-serious
  1113.        (msg
  1114.         (cond ((and error (file-attributes buffer-file-name))
  1115.            (setq buffer-read-only t)
  1116.            (gettext "File exists, but cannot be read."))
  1117.           ((not buffer-read-only)
  1118.            (if (and warn
  1119.                 (file-newer-than-file-p (make-auto-save-file-name)
  1120.                             buffer-file-name))
  1121.                (format "%s has auto save data; consider M-x recover-file"
  1122.                    (file-name-nondirectory buffer-file-name))
  1123.              (setq not-serious t)
  1124.              (if error (gettext "(New file)") nil)))
  1125.           ((not error)
  1126.            (setq not-serious t)
  1127.            (gettext "Note: file is write protected"))
  1128.           ((file-attributes (directory-file-name default-directory))
  1129.            (gettext "File not found and directory write-protected"))
  1130.           ((file-exists-p (file-name-directory buffer-file-name))
  1131.            (setq buffer-read-only nil))
  1132.           (t
  1133.            ;; If the directory the buffer is in doesn't exist,
  1134.            ;; offer to create it.  It's better to do this now
  1135.            ;; than when we save the buffer, because we want
  1136.            ;; autosaving to work.
  1137.            (setq buffer-read-only nil)
  1138.            ;; XEmacs
  1139.            (or (file-exists-p (file-name-directory buffer-file-name))
  1140.                (if (yes-or-no-p
  1141.                 (format
  1142.                  "The directory containing %s does not exist.  Create? "
  1143.                  (abbreviate-file-name buffer-file-name)))
  1144.                (make-directory (file-name-directory
  1145.                         buffer-file-name)
  1146.                        t)))
  1147.            nil))))
  1148.       (if msg
  1149.       (progn
  1150.         (message "%s" msg)
  1151.         (or not-serious (sit-for 1 t)))))
  1152.     (if (and auto-save-default (not noauto))
  1153.     (auto-save-mode t)))
  1154.   (unless nomodes
  1155.     (normal-mode t)
  1156.     (run-hooks 'find-file-hooks)))
  1157.  
  1158. (defun normal-mode (&optional find-file)
  1159.   "Choose the major mode for this buffer automatically.
  1160. Also sets up any specified local variables of the file.
  1161. Uses the visited file name, the -*- line, and the local variables spec.
  1162.  
  1163. This function is called automatically from `find-file'.  In that case,
  1164. we may set up specified local variables depending on the value of
  1165. `enable-local-variables': if it is t, we do; if it is nil, we don't;
  1166. otherwise, we query.  `enable-local-variables' is ignored if you
  1167. run `normal-mode' explicitly."
  1168.   (interactive)
  1169.   (or find-file (funcall (or default-major-mode 'fundamental-mode)))
  1170.   (and (condition-case err
  1171.            (progn (set-auto-mode)
  1172.                   t)
  1173.          (error (message "File mode specification error: %s"
  1174.                          (prin1-to-string err))
  1175.                 nil))
  1176.        (condition-case err
  1177.            (hack-local-variables (not find-file))
  1178.          (error (message "File local-variables error: %s"
  1179.                          (prin1-to-string err))))))
  1180.  
  1181. (defvar auto-mode-alist
  1182.   '(("\\.te?xt\\'" . text-mode)
  1183.     ("\\.[ch]\\'" . c-mode)
  1184.     ("\\.el\\'" . emacs-lisp-mode)
  1185.     ("\\.\\([CH]\\|cc\\|hh\\)\\'" . c++-mode)
  1186.     ("\\.[ch]\\(pp\\|xx\\|\\+\\+\\)\\'" . c++-mode)
  1187.     ("\\.java\\'" . java-mode)
  1188.     ("\\.f\\(or\\)?\\'" . fortran-mode)
  1189.     ("\\.F\\(OR\\)?\\'" . fortran-mode)
  1190.     ("\\.[fF]90\\'" . f90-mode)
  1191. ;;; Less common extensions come here
  1192. ;;; so more common ones above are found faster.
  1193.     ("\\.p[lm]\\'" . perl-mode)
  1194.     ("\\.py\\'" . python-mode)
  1195.     ("\\.texi\\(nfo\\)?\\'" . texinfo-mode)
  1196.     ("\\.ad[abs]\\'" . ada-mode)
  1197.     ("\\.c?l\\(i?sp\\)?\\'" . lisp-mode)
  1198.     ("\\.p\\(as\\)?\\'" . pascal-mode)
  1199.     ("\\.ltx\\'" . latex-mode)
  1200.     ("\\.[sS]\\'" . asm-mode)
  1201.     ("[Cc]hange.?[Ll]og?\\(.[0-9]+\\)?\\'" . change-log-mode)
  1202.     ("\\$CHANGE_LOG\\$\\.TXT" . change-log-mode)
  1203.     ("\\.scm\\(\\.[0-9]*\\)?\\'" . scheme-mode)
  1204.     ("\\.e\\'" . eiffel-mode)
  1205.     ("\\.mss\\'" . scribe-mode)
  1206.     ("\\.m\\([mes]\\|an\\)\\'" . nroff-mode)
  1207.     ("\\.icn\\'" . icon-mode)
  1208.     ("\\.\\([ckz]?sh\\|shar\\)\\'" . sh-mode)
  1209.     ("/\\.\\(bash_\\|z\\)?\\(profile\\|login\||logout\\)\\'" . sh-mode)
  1210.     ("/\\.\\([ckz]sh\\|bash\\|tcsh\\|es\\|xinit\\|startx\\)rc\\'" . sh-mode)
  1211.     ("/\\.\\([kz]shenv\\|xsession\\)\\'" . sh-mode)
  1212. ;;; The following should come after the ChangeLog pattern
  1213. ;;; for the sake of ChangeLog.1, etc.
  1214. ;;; and after the .scm.[0-9] pattern too.
  1215.     ("\\.[12345678]\\'" . nroff-mode)
  1216.     ("\\.[tT]e[xX]\\'" . tex-mode)
  1217.     ("\\.\\(sty\\|cls\\|bbl\\)\\'" . latex-mode)
  1218.     ("\\.bib\\'" . bibtex-mode)
  1219.     ("\\.article\\'" . text-mode)
  1220.     ("\\.letter\\'" . text-mode)
  1221.     ("\\.\\(tcl\\|exp\\)\\'" . tcl-mode)
  1222.     ("\\.wrl\\'" . vrml-mode)
  1223.     ("\\.awk\\'" . awk-mode)
  1224.     ("\\.prolog\\'" . prolog-mode)
  1225.     ("\\.tar\\'" . tar-mode)
  1226.     ("\\.\\(arc\\|zip\\|lzh\\|zoo\\)\\'" . archive-mode)
  1227.     ;; Mailer puts message to be edited in
  1228.     ;; /tmp/Re.... or Message
  1229.     ("^/tmp/Re" . text-mode)
  1230.     ("/Message[0-9]*\\'" . text-mode)
  1231.     ("/drafts/[0-9]+\\'" . mh-letter-mode)
  1232.     ;; some news reader is reported to use this
  1233.     ("^/tmp/fol/" . text-mode)
  1234.     ("\\.y\\'" . c-mode)
  1235.     ("\\.lex\\'" . c-mode)
  1236.     ("\\.m\\'" . objc-mode)
  1237.     ("\\.oak\\'" . scheme-mode)
  1238.     ("\\.s?html?\\'" . html-mode)
  1239.     ("\\.htm?l?3\\'" . html3-mode)
  1240.     ("\\.\\(sgml?\\|dtd\\)\\'" . sgml-mode)
  1241.     ("\\.c?ps\\'" . postscript-mode)
  1242.     ;; .emacs following a directory delimiter
  1243.     ;; in either Unix or VMS syntax.
  1244.     ("[]>:/]\\..*emacs\\'" . emacs-lisp-mode)
  1245.     ;; _emacs following a directory delimiter
  1246.     ;; in MsDos syntax
  1247.     ("[:/]_emacs\\'" . emacs-lisp-mode)
  1248.     ("\\.m4\\'" . autoconf-mode)
  1249.     ("configure\\.in\\'" . autoconf-mode)
  1250.     ("\\.ml\\'" . lisp-mode)
  1251.     ("\\.ma?k\\'" . makefile-mode)
  1252.     ("[Mm]akefile\\(\\.\\|\\'\\)" . makefile-mode)
  1253.     ("\\.X\\(defaults\\|environment\\|resources\\|modmap\\)\\'" . xrdb-mode)
  1254.     ("/app-defaults/" . xrdb-mode)
  1255.     ("\\.[^/]*wm\\'" . winmgr-mode)
  1256.     ("\\.[^/]*wm2?rc" . winmgr-mode)
  1257.     ("\\.[Jj][Pp][Ee]?[Gg]\\'" . image-mode)
  1258.     ("\\.[Pp][Nn][Gg]\\'" . image-mode)
  1259.     ("\\.[Gg][Ii][Ff]\\'" . image-mode)
  1260.     )
  1261. "Alist of filename patterns vs. corresponding major mode functions.
  1262. Each element looks like (REGEXP . FUNCTION) or (REGEXP FUNCTION NON-NIL).
  1263. \(NON-NIL stands for anything that is not nil; the value does not matter.)
  1264. Visiting a file whose name matches REGEXP specifies FUNCTION as the
  1265. mode function to use.  FUNCTION will be called, unless it is nil.
  1266.  
  1267. If the element has the form (REGEXP FUNCTION NON-NIL), then after
  1268. calling FUNCTION (if it's not nil), we delete the suffix that matched
  1269. REGEXP and search the list again for another match.")
  1270.  
  1271. (defconst interpreter-mode-alist
  1272.   '(("^#!.*csh"      . sh-mode)
  1273.     ("^#!.*sh\\b" . sh-mode)
  1274.     ("^#!.*\\b\\(scope\\|wish\\|tcl\\|expect\\)" . tcl-mode)
  1275.     ("perl"   . perl-mode)
  1276.     ("python" . python-mode)
  1277.     ("awk\\b" . awk-mode)
  1278.     ("rexx"   . rexx-mode)
  1279.     ("scm"    . scheme-mode)
  1280.     ("^:"     . sh-mode))
  1281.   "Alist mapping interpreter names to major modes.
  1282. This alist is used to guess the major mode of a file based on the
  1283. contents of the first line.  This line often contains something like:
  1284. #!/bin/sh
  1285. but may contain something more imaginative like
  1286. #! /bin/env python
  1287. or
  1288. eval 'exec perl -w -S $0 ${1+\"$@\"}'.
  1289.  
  1290. Each alist element looks like (INTERPRETER . MODE).
  1291. The car of each element is a regular expression which is compared
  1292. with the name of the interpreter specified in the first line.
  1293. If it matches, mode MODE is selected.")
  1294.  
  1295. (defconst inhibit-first-line-modes-regexps (purecopy '("\\.tar\\'"))
  1296.   "List of regexps; if one matches a file name, don't look for `-*-'.")
  1297.  
  1298. (defconst inhibit-first-line-modes-suffixes nil
  1299.   "List of regexps for what to ignore, for `inhibit-first-line-modes-regexps'.
  1300. When checking `inhibit-first-line-modes-regexps', we first discard
  1301. from the end of the file name anything that matches one of these regexps.")
  1302.  
  1303. (defvar user-init-file
  1304.   "" ; set by command-line
  1305.   "File name including directory of user's initialization file.")
  1306.  
  1307. (defun set-auto-mode ()
  1308.   "Select major mode appropriate for current buffer.
  1309. This checks for a -*- mode tag in the buffer's text,
  1310. compares the filename against the entries in `auto-mode-alist',
  1311. or checks the interpreter that runs this file against
  1312. `interpreter-mode-alist'.
  1313.  
  1314. It does not check for the `mode:' local variable in the
  1315. Local Variables section of the file; for that, use `hack-local-variables'.
  1316.  
  1317. If `enable-local-variables' is nil, this function does not check for a
  1318. -*- mode tag."
  1319.   (save-excursion
  1320.     ;; Look for -*-MODENAME-*- or -*- ... mode: MODENAME; ... -*-
  1321.     ;; Do this by calling the hack-local-variables helper to avoid redundancy.
  1322.     ;; We bind enable-local-variables to nil this time because we're going to
  1323.     ;; call hack-local-variables-prop-line again later, "for real."
  1324.     (or (let ((enable-local-variables nil))
  1325.       (hack-local-variables-prop-line nil))
  1326.     ;; It's not in the -*- line, so check the auto-mode-alist, unless
  1327.     ;; this buffer isn't associated with a file.
  1328.     (null buffer-file-name)
  1329.     (let ((name (file-name-sans-versions buffer-file-name))
  1330.               (keep-going t))
  1331.           (while keep-going
  1332.             (setq keep-going nil)
  1333.             (let ((alist auto-mode-alist)
  1334.                   (mode nil))
  1335.               ;; Find first matching alist entry.
  1336.           (let ((case-fold-search 
  1337.              (memq system-type '(vax-vms windows-nt))))
  1338.         (while (and (not mode) alist)
  1339.           (if (string-match (car (car alist)) name)
  1340.               (if (and (consp (cdr (car alist)))
  1341.                    (nth 2 (car alist)))
  1342.               (progn
  1343.                 (setq mode (car (cdr (car alist)))
  1344.                   name (substring name 0 (match-beginning 0))
  1345.                   keep-going t))
  1346.             (setq mode (cdr (car alist))
  1347.                   keep-going nil)))
  1348.           (setq alist (cdr alist))))
  1349.               ;; If we can't deduce a mode from the file name,
  1350.               ;; look for an interpreter specified in the first line.
  1351.           (if (and (null mode)
  1352.                (save-excursion ; XEmacs
  1353.              (goto-char (point-min))
  1354.              (looking-at "#!")))
  1355.                   (let ((firstline
  1356.                          (buffer-substring
  1357.                           (point-min)
  1358.                           (save-excursion
  1359.                             (goto-char (point-min)) (end-of-line) (point)))))
  1360.                     (setq alist interpreter-mode-alist)
  1361.                     (while alist
  1362.                       (if (string-match (car (car alist)) firstline)
  1363.                           (progn
  1364.                             (setq mode (cdr (car alist)))
  1365.                             (setq alist nil))
  1366.                         (setq alist (cdr alist))))))
  1367.               (if mode
  1368.                   (funcall mode))
  1369.               ))))))
  1370.  
  1371. (defvar hack-local-variables-hook nil
  1372.   "Normal hook run after processing a file's local variables specs.
  1373. Major modes can use this to examine user-specified local variables
  1374. in order to initialize other data structure based on them.
  1375.  
  1376. This hook runs even if there were no local variables or if their
  1377. evaluation was suppressed.  See also `enable-local-variables' and
  1378. `enable-local-eval'.")
  1379.  
  1380. (defun hack-local-variables (&optional force)
  1381.   "Parse, and bind or evaluate as appropriate, any local variables
  1382. for current buffer."
  1383.   ;; Don't look for -*- if this file name matches any
  1384.   ;; of the regexps in inhibit-first-line-modes-regexps.
  1385.   (if (or (null buffer-file-name) ; don't lose if buffer has no file!
  1386.       (not (let ((temp inhibit-first-line-modes-regexps)
  1387.              (name (if buffer-file-name
  1388.                    (file-name-sans-versions buffer-file-name)
  1389.                  (buffer-name))))
  1390.          (while (let ((sufs inhibit-first-line-modes-suffixes))
  1391.               (while (and sufs (not
  1392.                         (string-match (car sufs) name)))
  1393.                 (setq sufs (cdr sufs)))
  1394.               sufs)
  1395.            (setq name (substring name 0 (match-beginning 0))))
  1396.          (while (and temp
  1397.                  (not (string-match (car temp) name)))
  1398.            (setq temp (cdr temp))
  1399.            temp))))
  1400.       (progn
  1401.         ;; Look for variables in the -*- line.
  1402.         (hack-local-variables-prop-line force)
  1403.         ;; Look for "Local variables:" block in last page.
  1404.         (hack-local-variables-last-page force)))
  1405.   (run-hooks 'hack-local-variables-hook))
  1406.  
  1407. ;;; Local variables may be specified in the last page of the file (within 3k
  1408. ;;; from the end of the file and after the last ^L) in the form
  1409. ;;;
  1410. ;;;   Local variables:
  1411. ;;;   variable-name: variable-value
  1412. ;;;   end:
  1413. ;;;
  1414. ;;; The lines may begin with a common prefix, like ";;;   " in the above
  1415. ;;; example.  They may also have a common suffix (" */" for example).  In 
  1416. ;;; this form, the local variable "mode" can be used to change the major 
  1417. ;;; mode, and the local variable "eval" can be used to evaluate an arbitrary
  1418. ;;; form.
  1419. ;;;
  1420. ;;; Local variables may also be specified in the first line of the file.
  1421. ;;; Embedded in this line are a pair of "-*-" sequences.  What lies between
  1422. ;;; them are variable-name/variable-value pairs, like:
  1423. ;;;
  1424. ;;;     -*- mode: emacs-lisp -*-
  1425. ;;; or     -*- mode: postscript; version-control: never -*-
  1426. ;;; or     -*- tags-file-name: "/foo/bar/TAGS" -*-
  1427. ;;;
  1428. ;;; The local variable "eval" is not used with this form. For hysterical
  1429. ;;; reasons, the syntax "-*- modename -*-" is allowed as well.
  1430. ;;;
  1431.  
  1432. (defun hack-local-variables-p (modeline)
  1433.   (or (eq enable-local-variables t)
  1434.       (and enable-local-variables
  1435.            (save-window-excursion
  1436.              (condition-case nil
  1437.                  (switch-to-buffer (current-buffer))
  1438.                (error
  1439.                 ;; If we fail to switch in the selected window,
  1440.                 ;; it is probably a minibuffer.
  1441.                 ;; So try another window.
  1442.                 (condition-case nil
  1443.                     (switch-to-buffer-other-window (current-buffer))
  1444.                   (error
  1445.                    (switch-to-buffer-other-frame (current-buffer))))))
  1446.              (or modeline (save-excursion
  1447.                              (beginning-of-line)
  1448.                              (set-window-start (selected-window) (point))))
  1449.              (y-or-n-p (format
  1450.                         "Set local variables as specified %s of %s? "
  1451.                         (if modeline "in -*- line" "at end")
  1452.                         (if buffer-file-name
  1453.                             (file-name-nondirectory buffer-file-name)
  1454.                             (concat "buffer " (buffer-name)))))))))
  1455.  
  1456. (defun hack-local-variables-last-page (&optional force)
  1457.   ;; Set local variables set in the "Local Variables:" block of the last page.
  1458.   (save-excursion
  1459.     (goto-char (point-max))
  1460.     (search-backward "\n\^L" (max (- (point-max) 3000) (point-min)) 'move)
  1461.     (if (let ((case-fold-search t))
  1462.       (and (search-forward "Local Variables:" nil t)
  1463.            (or force
  1464.                    (hack-local-variables-p nil))))
  1465.     (let ((continue t)
  1466.           prefix prefixlen suffix beg
  1467.               (enable-local-eval enable-local-eval))
  1468.       ;; The prefix is what comes before "local variables:" in its line.
  1469.       ;; The suffix is what comes after "local variables:" in its line.
  1470.       (skip-chars-forward " \t")
  1471.       (or (eolp)
  1472.           (setq suffix (buffer-substring (point)
  1473.                          (progn (end-of-line) (point)))))
  1474.       (goto-char (match-beginning 0))
  1475.       (or (bolp)
  1476.           (setq prefix
  1477.             (buffer-substring (point)
  1478.                       (progn (beginning-of-line) (point)))))
  1479.       (if prefix (setq prefixlen (length prefix)
  1480.                prefix (regexp-quote prefix)))
  1481.       (if suffix (setq suffix (concat (regexp-quote suffix) "$")))
  1482.       (while continue
  1483.         ;; Look at next local variable spec.
  1484.         (if selective-display (re-search-forward "[\n\C-m]")
  1485.           (forward-line 1))
  1486.         ;; Skip the prefix, if any.
  1487.         (if prefix
  1488.         (if (looking-at prefix)
  1489.             (forward-char prefixlen)
  1490.           (error "Local variables entry is missing the prefix")))
  1491.         ;; Find the variable name; strip whitespace.
  1492.         (skip-chars-forward " \t")
  1493.         (setq beg (point))
  1494.         (skip-chars-forward "^:\n")
  1495.         (if (eolp) (error "Missing colon in local variables entry"))
  1496.         (skip-chars-backward " \t")
  1497.         (let* ((str (buffer-substring beg (point)))
  1498.            (var (read str))
  1499.           val)
  1500.           ;; Setting variable named "end" means end of list.
  1501.           (if (string-equal (downcase str) "end")
  1502.           (setq continue nil)
  1503.         ;; Otherwise read the variable value.
  1504.         (skip-chars-forward "^:")
  1505.         (forward-char 1)
  1506.         (setq val (read (current-buffer)))
  1507.         (skip-chars-backward "\n")
  1508.         (skip-chars-forward " \t")
  1509.         (or (if suffix (looking-at suffix) (eolp))
  1510.             (error "Local variables entry is terminated incorrectly"))
  1511.         ;; Set the variable.  "Variables" mode and eval are funny.
  1512.                 (hack-one-local-variable var val))))))))
  1513.  
  1514. ;; jwz - New Version 20.1/19.15
  1515. (defun hack-local-variables-prop-line (&optional force)
  1516.   ;; Set local variables specified in the -*- line.
  1517.   ;; Returns t if mode was set.
  1518.   (let ((result nil))
  1519.     (save-excursion
  1520.       (goto-char (point-min))
  1521.       (skip-chars-forward " \t\n\r")
  1522.       (let ((end (save-excursion 
  1523.            ;; If the file begins with "#!"
  1524.            ;; (un*x exec interpreter magic), look
  1525.            ;; for mode frobs in the first two
  1526.            ;; lines.  You cannot necessarily
  1527.            ;; put them in the first line of
  1528.            ;; such a file without screwing up
  1529.            ;; the interpreter invocation.
  1530.            (end-of-line (and (looking-at "^#!") 2))
  1531.            (point))))
  1532.     ;; Parse the -*- line into the `result' alist.
  1533.     (cond ((not (search-forward "-*-" end t))
  1534.            ;; doesn't have one.
  1535.            (setq force t))
  1536.           ((looking-at "[ \t]*\\([^ \t\n\r:;]+\\)\\([ \t]*-\\*-\\)")
  1537.            ;; Antiquated form: "-*- ModeName -*-".
  1538.            (setq result
  1539.              (list (cons 'mode
  1540.                  (intern (buffer-substring
  1541.                       (match-beginning 1)
  1542.                       (match-end 1)))))
  1543.              ))
  1544.           (t
  1545.            ;; Usual form: '-*-' [ <variable> ':' <value> ';' ]* '-*-'
  1546.            ;; (last ";" is optional).
  1547.            (save-excursion
  1548.          (if (search-forward "-*-" end t)
  1549.              (setq end (- (point) 3))
  1550.            (error "-*- not terminated before end of line")))
  1551.            (while (< (point) end)
  1552.          (or (looking-at "[ \t]*\\([^ \t\n:]+\\)[ \t]*:[ \t]*")
  1553.              (error "malformed -*- line"))
  1554.          (goto-char (match-end 0))
  1555.          ;; There used to be a downcase here,
  1556.          ;; but the manual didn't say so,
  1557.          ;; and people want to set var names that aren't all lc.
  1558.          (let ((key (intern (buffer-substring
  1559.                      (match-beginning 1)
  1560.                      (match-end 1))))
  1561.                (val (save-restriction
  1562.                   (narrow-to-region (point) end)
  1563.                   (read (current-buffer)))))
  1564.            ;; Case sensitivity!  Icepicks in my forehead!
  1565.            (if (equal (downcase (symbol-name key)) "mode")
  1566.                (setq key 'mode))
  1567.            (setq result (cons (cons key val) result))
  1568.            (skip-chars-forward " \t;")))
  1569.            (setq result (nreverse result))))))
  1570.     
  1571.     (let ((set-any-p (or force (hack-local-variables-p t)))
  1572.       (mode-p nil))
  1573.       (while result
  1574.     (let ((key (car (car result)))
  1575.           (val (cdr (car result))))
  1576.       (cond ((eq key 'mode)
  1577.          (and enable-local-variables
  1578.               (setq mode-p t)
  1579.               (funcall (intern (concat (downcase (symbol-name val))
  1580.                            "-mode")))))
  1581.         (set-any-p
  1582.          (hack-one-local-variable key val))
  1583.         (t
  1584.          nil)))
  1585.     (setq result (cdr result)))
  1586.       mode-p)))
  1587.  
  1588. (defconst ignored-local-variables
  1589.   (list 'enable-local-eval)
  1590.   "Variables to be ignored in a file's local variable spec.")
  1591.  
  1592. ;; Get confirmation before setting these variables as locals in a file.
  1593. (put 'debugger 'risky-local-variable t)
  1594. (put 'enable-local-eval 'risky-local-variable t)
  1595. (put 'ignored-local-variables 'risky-local-variable t)
  1596. (put 'eval 'risky-local-variable t)
  1597. (put 'file-name-handler-alist 'risky-local-variable t)
  1598. (put 'minor-mode-map-alist 'risky-local-variable t)
  1599. (put 'after-load-alist 'risky-local-variable t)
  1600. (put 'buffer-file-name 'risky-local-variable t)
  1601. (put 'buffer-auto-save-file-name 'risky-local-variable t)
  1602. (put 'buffer-file-truename 'risky-local-variable t)
  1603. (put 'exec-path 'risky-local-variable t)
  1604. (put 'load-path 'risky-local-variable t)
  1605. (put 'exec-directory 'risky-local-variable t)
  1606. (put 'process-environment 'risky-local-variable t)
  1607. ;; Don't wait for outline.el to be loaded, for the sake of outline-minor-mode.
  1608. (put 'outline-level 'risky-local-variable t)
  1609. (put 'rmail-output-file-alist 'risky-local-variable t)
  1610.         
  1611. ;; This one is safe because the user gets to check it before it is used.
  1612. (put 'compile-command 'safe-local-variable t)
  1613.  
  1614. ;(defun hack-one-local-variable-quotep (exp)
  1615. ;  (and (consp exp) (eq (car exp) 'quote) (consp (cdr exp))))
  1616.  
  1617. ;; "Set" one variable in a local variables spec.
  1618. ;; A few variable names are treated specially.
  1619. (defun hack-one-local-variable (var val)
  1620.   (cond ((eq var 'mode)
  1621.      (funcall (intern (concat (downcase (symbol-name val))
  1622.                   "-mode"))))
  1623.     ((memq var ignored-local-variables)
  1624.      nil)
  1625.     ;; "Setting" eval means either eval it or do nothing.
  1626.     ;; Likewise for setting hook variables.
  1627.     ((or (get var 'risky-local-variable)
  1628.          (and
  1629.           (string-match "-hooks?$\\|-functions?$\\|-forms?$\\|-program$\\|-command$"
  1630.                 (symbol-name var))
  1631.           (not (get var 'safe-local-variable))))
  1632. ;     ;; Permit evaling a put of a harmless property
  1633. ;     ;; if the args do nothing tricky.
  1634. ;     (if (or (and (eq var 'eval)
  1635. ;              (consp val)
  1636. ;              (eq (car val) 'put)
  1637. ;              (hack-one-local-variable-quotep (nth 1 val))
  1638. ;              (hack-one-local-variable-quotep (nth 2 val))
  1639. ;              ;; Only allow safe values of lisp-indent-hook;
  1640. ;              ;; not functions.
  1641. ;              (or (numberp (nth 3 val))
  1642. ;              (equal (nth 3 val) ''defun))
  1643. ;              (memq (nth 1 (nth 2 val))
  1644. ;                '(lisp-indent-hook)))
  1645.      (if (and (not (zerop (user-uid)))
  1646.           (or (eq enable-local-eval t)
  1647.               (and enable-local-eval
  1648.                (save-window-excursion
  1649.                  (switch-to-buffer (current-buffer))
  1650.                  (save-excursion
  1651.                    (beginning-of-line)
  1652.                    (set-window-start (selected-window) (point)))
  1653.                  (setq enable-local-eval
  1654.                    (y-or-n-p (format "Process `eval' or hook local variables in file %s? "
  1655.                              (file-name-nondirectory buffer-file-name))))))))
  1656.          (if (eq var 'eval)
  1657.          (save-excursion (eval val))
  1658.            (make-local-variable var)
  1659.            (set var val))
  1660.        (message "Ignoring `eval:' in file's local variables")))
  1661.     ;; Ordinary variable, really set it.
  1662.     (t (make-local-variable var)
  1663.        (set var val))))
  1664.  
  1665. (defun set-visited-file-name (filename)
  1666.   "Change name of file visited in current buffer to FILENAME.
  1667. The next time the buffer is saved it will go in the newly specified file.
  1668. nil or empty string as argument means make buffer not be visiting any file.
  1669. Remember to delete the initial contents of the minibuffer
  1670. if you wish to pass an empty string as the argument."
  1671.   (interactive "FSet visited file name: ")
  1672.   (if (buffer-base-buffer)
  1673.       (error "An indirect buffer cannot visit a file"))
  1674.   (let (truename)
  1675.     (if filename
  1676.     (setq filename
  1677.           (if (string-equal filename "")
  1678.           nil
  1679.         (expand-file-name filename))))
  1680.     (if filename
  1681.     (progn
  1682.       (setq truename (file-truename filename))
  1683.       ;; #### Do we need to check if truename is non-nil?
  1684.       (if find-file-use-truenames
  1685.           (setq filename truename))))
  1686.     (or (equal filename buffer-file-name)
  1687.     (progn
  1688.       (and filename (lock-buffer filename))
  1689.       (unlock-buffer)))
  1690.     (setq buffer-file-name filename)
  1691.     (if filename            ; make buffer name reflect filename.
  1692.     (let ((new-name (file-name-nondirectory buffer-file-name)))
  1693.       (if (string= new-name "")
  1694.           (error "Empty file name"))
  1695.       (if (eq system-type 'vax-vms)
  1696.           (setq new-name (downcase new-name)))
  1697.       (setq default-directory (file-name-directory buffer-file-name))
  1698.       (or (string= new-name (buffer-name))
  1699.           (rename-buffer new-name t))))
  1700.     (setq buffer-backed-up nil)
  1701.     (clear-visited-file-modtime)
  1702.     (compute-buffer-file-truename) ; insert-file-contents does this too.
  1703. ;    ;; Abbreviate the file names of the buffer.
  1704. ;    (if truename
  1705. ;     (progn
  1706. ;       (setq buffer-file-truename (abbreviate-file-name truename))
  1707. ;       (if find-file-visit-truename
  1708. ;           (setq buffer-file-name buffer-file-truename))))
  1709.     (setq buffer-file-number
  1710.       (if filename
  1711.           (nthcdr 10 (file-attributes buffer-file-name))
  1712.           nil)))
  1713.   ;; write-file-hooks is normally used for things like ftp-find-file
  1714.   ;; that visit things that are not local files as if they were files.
  1715.   ;; Changing to visit an ordinary local file instead should flush the hook.
  1716.   (kill-local-variable 'write-file-hooks)
  1717.   (kill-local-variable 'after-save-hook)
  1718.   (kill-local-variable 'local-write-file-hooks)
  1719.   (kill-local-variable 'write-file-data-hooks)
  1720.   (kill-local-variable 'revert-buffer-function)
  1721.   (kill-local-variable 'backup-inhibited)
  1722.   ;; If buffer was read-only because of version control,
  1723.   ;; that reason is gone now, so make it writable.
  1724.   (if (and (boundp 'vc-mode) vc-mode)
  1725.       (setq buffer-read-only nil))
  1726.   (kill-local-variable 'vc-mode)
  1727.   ;; Turn off backup files for certain file names.
  1728.   ;; Since this is a permanent local, the major mode won't eliminate it.
  1729.   (and (not (funcall backup-enable-predicate buffer-file-name))
  1730.        (progn
  1731.      (make-local-variable 'backup-inhibited)
  1732.      (setq backup-inhibited t)))
  1733.   (let ((oauto buffer-auto-save-file-name))
  1734.     ;; If auto-save was not already on, turn it on if appropriate.
  1735.     (if (not buffer-auto-save-file-name)
  1736.     (and buffer-file-name auto-save-default
  1737.          (auto-save-mode t))
  1738.       ;; If auto save is on, start using a new name.
  1739.       ;; We deliberately don't rename or delete the old auto save
  1740.       ;; for the old visited file name.  This is because perhaps
  1741.       ;; the user wants to save the new state and then compare with the
  1742.       ;; previous state from the auto save file.
  1743.       (setq buffer-auto-save-file-name
  1744.         (make-auto-save-file-name)))
  1745.     ;; Rename the old auto save file if any.
  1746.     (and oauto buffer-auto-save-file-name
  1747.      (file-exists-p oauto)
  1748.      (rename-file oauto buffer-auto-save-file-name t)))
  1749.   (if buffer-file-name
  1750.       (set-buffer-modified-p t))
  1751.   ;; #### ??
  1752.   (run-hooks 'after-set-visited-file-name-hooks))
  1753.  
  1754. (defun write-file (filename &optional confirm codesys)
  1755.   "Write current buffer into file FILENAME.
  1756. Makes buffer visit that file, and marks it not modified.
  1757. If the buffer is already visiting a file, you can specify
  1758. a directory name as FILENAME, to write a file of the same
  1759. old name in that directory.
  1760. If optional second arg CONFIRM is non-nil,
  1761. ask for confirmation for overwriting an existing file.
  1762. Under XEmacs/Mule, optional third argument specifies the
  1763. coding system to use when encoding the file.  Interactively,
  1764. with a prefix argument, you will be prompted for the coding system."
  1765. ;;  (interactive "FWrite file: ")
  1766.   (interactive
  1767.    (list (if buffer-file-name
  1768.          (read-file-name "Write file: "
  1769.                  nil nil nil nil)
  1770.        (read-file-name "Write file: "
  1771.                    (cdr (assq 'default-directory
  1772.                       (buffer-local-variables)))
  1773.                    nil nil (buffer-name)))
  1774.      t
  1775.      (if (and current-prefix-arg (featurep 'mule))
  1776.          (read-coding-system "Coding system: "))))
  1777.   (and (eq (current-buffer) mouse-grabbed-buffer)
  1778.        (error "Can't write minibuffer window"))
  1779.   (or (null filename) (string-equal filename "")
  1780.       (progn
  1781.     ;; If arg is just a directory,
  1782.     ;; use same file name, but in that directory.
  1783.     (if (and (file-directory-p filename) buffer-file-name)
  1784.         (setq filename (concat (file-name-as-directory filename)
  1785.                    (file-name-nondirectory buffer-file-name))))
  1786.     (and confirm
  1787.          (file-exists-p filename)
  1788.          (or (y-or-n-p (format "File `%s' exists; overwrite? " filename))
  1789.          (error "Canceled")))
  1790.     (set-visited-file-name filename)))
  1791.   (set-buffer-modified-p t)
  1792.   (setq buffer-read-only nil)
  1793.   (if codesys
  1794.       (let ((buffer-file-coding-system (get-coding-system codesys)))
  1795.     (save-buffer))
  1796.     (save-buffer)))
  1797.  
  1798. (defun backup-buffer ()
  1799.   "Make a backup of the disk file visited by the current buffer, if appropriate.
  1800. This is normally done before saving the buffer the first time.
  1801. If the value is non-nil, it is the result of `file-modes' on the original file;
  1802. this means that the caller, after saving the buffer, should change the modes
  1803. of the new file to agree with the old modes."
  1804.   (if buffer-file-name
  1805.       (let ((handler (find-file-name-handler buffer-file-name 'backup-buffer)))
  1806.     (if handler
  1807.         (funcall handler 'backup-buffer)
  1808.       (if (and make-backup-files
  1809.            (not backup-inhibited)
  1810.            (not buffer-backed-up)
  1811.            (file-exists-p buffer-file-name)
  1812.            (memq (aref (elt (file-attributes buffer-file-name) 8) 0)
  1813.              '(?- ?l)))
  1814.           (let ((real-file-name buffer-file-name)
  1815.             backup-info backupname targets setmodes)
  1816.         ;; If specified name is a symbolic link, chase it to the target.
  1817.         ;; Thus we make the backups in the directory where the real file is.
  1818.         (setq real-file-name (file-chase-links real-file-name))
  1819.         (setq backup-info (find-backup-file-name real-file-name)
  1820.               backupname (car backup-info)
  1821.               targets (cdr backup-info))
  1822. ;;;     (if (file-directory-p buffer-file-name)
  1823. ;;;         (error "Cannot save buffer in directory %s" buffer-file-name))
  1824.         (if backup-info
  1825.             (condition-case ()
  1826.             (let ((delete-old-versions
  1827.                    ;; If have old versions to maybe delete,
  1828.                    ;; ask the user to confirm now, before doing anything.
  1829.                    ;; But don't actually delete til later.
  1830.                    (and targets
  1831.                     (or (eq delete-old-versions t)
  1832.                     (eq delete-old-versions nil))
  1833.                     (or delete-old-versions
  1834.                     (y-or-n-p (format "Delete excess backup versions of %s? "
  1835.                               real-file-name))))))
  1836.               ;; Actually write the back up file.
  1837.               (condition-case ()
  1838.                   (if (or file-precious-flag
  1839.                     ;              (file-symlink-p buffer-file-name)
  1840.                       backup-by-copying
  1841.                       (and backup-by-copying-when-linked
  1842.                        (> (file-nlinks real-file-name) 1))
  1843.                       (and backup-by-copying-when-mismatch
  1844.                        (let ((attr (file-attributes real-file-name)))
  1845.                          (or (nth 9 attr)
  1846.                          (not (file-ownership-preserved-p real-file-name))))))
  1847.                   (condition-case ()
  1848.                       (copy-file real-file-name backupname t t)
  1849.                     (file-error
  1850.                      ;; If copying fails because file BACKUPNAME
  1851.                      ;; is not writable, delete that file and try again.
  1852.                      (if (and (file-exists-p backupname)
  1853.                           (not (file-writable-p backupname)))
  1854.                      (delete-file backupname))
  1855.                      (copy-file real-file-name backupname t t)))
  1856.                 ;; rename-file should delete old backup.
  1857.                 (rename-file real-file-name backupname t)
  1858.                 (setq setmodes (file-modes backupname)))
  1859.                 (file-error
  1860.                  ;; If trouble writing the backup, write it in ~.
  1861.                  (setq backupname (expand-file-name "~/%backup%~"))
  1862.                  (message "Cannot write backup file; backing up in ~/%%backup%%~")
  1863.                  (sleep-for 1)
  1864.                  (condition-case ()
  1865.                  (copy-file real-file-name backupname t t)
  1866.                    (file-error
  1867.                 ;; If copying fails because file BACKUPNAME
  1868.                 ;; is not writable, delete that file and try again.
  1869.                 (if (and (file-exists-p backupname)
  1870.                      (not (file-writable-p backupname)))
  1871.                     (delete-file backupname))
  1872.                 (copy-file real-file-name backupname t t)))))
  1873.               (setq buffer-backed-up t)
  1874.               ;; Now delete the old versions, if desired.
  1875.               (if delete-old-versions
  1876.                   (while targets
  1877.                 (condition-case ()
  1878.                     (delete-file (car targets))
  1879.                   (file-error nil))
  1880.                 (setq targets (cdr targets))))
  1881.               setmodes)
  1882.               (file-error nil)))))))))
  1883.  
  1884. (defun file-name-sans-versions (name &optional keep-backup-version)
  1885.   "Return FILENAME sans backup versions or strings.
  1886. This is a separate procedure so your site-init or startup file can
  1887. redefine it.
  1888. If the optional argument KEEP-BACKUP-VERSION is non-nil,
  1889. we do not remove backup version numbers, only true file version numbers."
  1890.   (let ((handler (find-file-name-handler name 'file-name-sans-versions)))
  1891.     (if handler
  1892.     (funcall handler 'file-name-sans-versions name keep-backup-version)
  1893.       (substring name 0
  1894.          (if (eq system-type 'vax-vms)
  1895.              ;; VMS version number is (a) semicolon, optional
  1896.              ;; sign, zero or more digits or (b) period, option
  1897.              ;; sign, zero or more digits, provided this is the
  1898.              ;; second period encountered outside of the
  1899.              ;; device/directory part of the file name.
  1900.              (or (string-match ";[-+]?[0-9]*\\'" name)
  1901.              (if (string-match "\\.[^]>:]*\\(\\.[-+]?[0-9]*\\)\\'"
  1902.                        name)
  1903.                  (match-beginning 1))
  1904.              (length name))
  1905.            (if keep-backup-version
  1906.                (length name)
  1907.              (or (string-match "\\.~[0-9.]+~\\'" name)
  1908.              ;; XEmacs - VC uses extensions like ".~tagname~" or ".~1.1.5.2~"
  1909.              (let ((pos (string-match "\\.~\\([^.~ \t]+\\|[0-9.]+\\)~\\'" name)))
  1910.                (and pos
  1911.                 ;; #### - is this filesystem check too paranoid?
  1912.                 (file-exists-p (substring name 0 pos))
  1913.                 pos))
  1914.              (string-match "~\\'" name)
  1915.              (length name))))))))
  1916.  
  1917. (defun file-ownership-preserved-p (file)
  1918.   "Returns t if deleting FILE and rewriting it would preserve the owner."
  1919.   (let ((handler (find-file-name-handler file 'file-ownership-preserved-p)))
  1920.     (if handler
  1921.     (funcall handler 'file-ownership-preserved-p file)
  1922.       (let ((attributes (file-attributes file)))
  1923.     ;; Return t if the file doesn't exist, since it's true that no
  1924.     ;; information would be lost by an (attempted) delete and create.
  1925.     (or (null attributes)
  1926.         (= (nth 2 attributes) (user-uid)))))))
  1927.  
  1928. (defun file-name-sans-extension (filename)
  1929.   "Return FILENAME sans final \"extension\".
  1930. The extension, in a file name, is the part that follows the last `.'."
  1931.   (save-match-data
  1932.     (let ((file (file-name-sans-versions (file-name-nondirectory filename)))
  1933.       directory)
  1934.       (if (string-match "\\.[^.]*\\'" file)
  1935.       (if (setq directory (file-name-directory filename))
  1936.           (expand-file-name (substring file 0 (match-beginning 0))
  1937.                 directory)
  1938.         (substring file 0 (match-beginning 0)))
  1939.     filename))))
  1940.  
  1941. (defun make-backup-file-name (file)
  1942.   "Create the non-numeric backup file name for FILE.
  1943. This is a separate function so you can redefine it for customization."
  1944.   (if (eq system-type 'ms-dos)
  1945.       (let ((fn (file-name-nondirectory file)))
  1946.     (concat (file-name-directory file)
  1947.         (if (string-match "\\([^.]*\\)\\(\\..*\\)?" fn)
  1948.             (substring fn 0 (match-end 1)))
  1949.         ".bak"))
  1950.     (concat file "~")))
  1951.  
  1952. (defun backup-file-name-p (file)
  1953.   "Return non-nil if FILE is a backup file name (numeric or not).
  1954. This is a separate function so you can redefine it for customization.
  1955. You may need to redefine `file-name-sans-versions' as well."
  1956.   (if (eq system-type 'ms-dos)
  1957.       (string-match "\\.bak\\'" file)
  1958.       (string-match "~\\'" file)))
  1959.  
  1960. ;; This is used in various files.
  1961. ;; The usage of bv-length is not very clean,
  1962. ;; but I can't see a good alternative,
  1963. ;; so as of now I am leaving it alone.
  1964. (defun backup-extract-version (fn)
  1965.   "Given the name of a numeric backup file, return the backup number.
  1966. Uses the free variable `bv-length', whose value should be
  1967. the index in the name where the version number begins."
  1968.   (declare (special bv-length))
  1969.   (if (and (string-match "[0-9]+~\\'" fn bv-length)
  1970.        (= (match-beginning 0) bv-length))
  1971.       (string-to-int (substring fn bv-length -1))
  1972.       0))
  1973.  
  1974. ;; I believe there is no need to alter this behavior for VMS;
  1975. ;; since backup files are not made on VMS, it should not get called.
  1976. (defun find-backup-file-name (fn)
  1977.   "Find a file name for a backup file, and suggestions for deletions.
  1978. Value is a list whose car is the name for the backup file
  1979.  and whose cdr is a list of old versions to consider deleting now.
  1980. If the value is nil, don't make a backup."
  1981.   (let ((handler (find-file-name-handler fn 'find-backup-file-name)))
  1982.     ;; Run a handler for this function so that ange-ftp can refuse to do it.
  1983.     (if handler
  1984.     (funcall handler 'find-backup-file-name fn)
  1985.       (if (eq version-control 'never)
  1986.       (list (make-backup-file-name fn))
  1987.     (let* ((base-versions (concat (file-name-nondirectory fn) ".~"))
  1988.            ;; used by backup-extract-version:
  1989.            (bv-length (length base-versions))
  1990.            possibilities
  1991.            (versions nil)
  1992.            (high-water-mark 0)
  1993.            (deserve-versions-p nil)
  1994.            (number-to-delete 0))
  1995.       (condition-case ()
  1996.           (setq possibilities (file-name-all-completions
  1997.                    base-versions
  1998.                    (file-name-directory fn))
  1999.             versions (sort (mapcar
  2000.                     #'backup-extract-version
  2001.                     possibilities)
  2002.                    '<)
  2003.             high-water-mark (apply #'max 0 versions)
  2004.             deserve-versions-p (or version-control
  2005.                        (> high-water-mark 0))
  2006.             number-to-delete (- (length versions)
  2007.                     kept-old-versions kept-new-versions -1))
  2008.         (file-error
  2009.          (setq possibilities nil)))
  2010.       (if (not deserve-versions-p)
  2011.           (list (make-backup-file-name fn))
  2012.         (cons (concat fn ".~" (int-to-string (1+ high-water-mark)) "~")
  2013.           (if (and (> number-to-delete 0)
  2014.                ;; Delete nothing if there is overflow
  2015.                ;; in the number of versions to keep.
  2016.                (>= (+ kept-new-versions kept-old-versions -1) 0))
  2017.               (mapcar #'(lambda (n)
  2018.                   (concat fn ".~" (int-to-string n) "~"))
  2019.                   (let ((v (nthcdr kept-old-versions versions)))
  2020.                 (rplacd (nthcdr (1- number-to-delete) v) ())
  2021.                 v))))))))))
  2022.  
  2023. (defun file-nlinks (filename)
  2024.   "Return number of names file FILENAME has."
  2025.   (car (cdr (file-attributes filename))))
  2026.  
  2027. (defun file-relative-name (filename &optional directory)
  2028.   "Convert FILENAME to be relative to DIRECTORY (default: default-directory)."
  2029.   (setq filename (expand-file-name filename)
  2030.     directory (file-name-as-directory (expand-file-name
  2031.                        (or directory default-directory))))
  2032.   (let ((ancestor ""))
  2033.     (while (not (string-match (concat "^" (regexp-quote directory)) filename))
  2034.       (setq directory (file-name-directory (substring directory 0 -1))
  2035.          ancestor (concat "../" ancestor)))
  2036.     (concat ancestor (substring filename (match-end 0)))))
  2037.  
  2038. (defun save-buffer (&optional args)
  2039.   "Save current buffer in visited file if modified.  Versions described below.
  2040.  
  2041. By default, makes the previous version into a backup file
  2042.  if previously requested or if this is the first save.
  2043. With 1 or 3 \\[universal-argument]'s, marks this version
  2044.  to become a backup when the next save is done.
  2045. With 2 or 3 \\[universal-argument]'s,
  2046.  unconditionally makes the previous version into a backup file.
  2047. With argument of 0, never makes the previous version into a backup file.
  2048.  
  2049. If a file's name is FOO, the names of its numbered backup versions are
  2050.  FOO.~i~ for various integers i.  A non-numbered backup file is called FOO~.
  2051. Numeric backups (rather than FOO~) will be made if value of
  2052.  `version-control' is not the atom `never' and either there are already
  2053.  numeric versions of the file being backed up, or `version-control' is
  2054.  non-nil.
  2055. We don't want excessive versions piling up, so there are variables
  2056.  `kept-old-versions', which tells XEmacs how many oldest versions to keep,
  2057.  and `kept-new-versions', which tells how many newest versions to keep.
  2058.  Defaults are 2 old versions and 2 new.
  2059. `dired-kept-versions' controls dired's clean-directory (.) command.
  2060. If `delete-old-versions' is nil, system will query user
  2061.  before trimming versions.  Otherwise it does it silently."
  2062.   (interactive "_p")
  2063.   (let ((modp (buffer-modified-p))
  2064.     (large (> (buffer-size) 50000))
  2065.     (make-backup-files (or (and make-backup-files (not (eq args 0)))
  2066.                    (memq args '(16 64)))))
  2067.     (and modp (memq args '(16 64)) (setq buffer-backed-up nil))
  2068.     (if (and modp large) (display-message
  2069.               'progress (format "Saving file %s..."
  2070.                         (buffer-file-name))))
  2071.     (basic-save-buffer)
  2072.     (and modp (memq args '(4 64)) (setq buffer-backed-up nil))))
  2073.  
  2074. (defun delete-auto-save-file-if-necessary (&optional force)
  2075.   "Delete auto-save file for current buffer if `delete-auto-save-files' is t.
  2076. Normally delete only if the file was written by this XEmacs
  2077. since the last real save, but optional arg FORCE non-nil means delete anyway."
  2078.   (and buffer-auto-save-file-name delete-auto-save-files
  2079.        (not (string= buffer-file-name buffer-auto-save-file-name))
  2080.        (or force (recent-auto-save-p))
  2081.        (progn
  2082.      (condition-case ()
  2083.          (delete-file buffer-auto-save-file-name)
  2084.        (file-error nil))
  2085.      (set-buffer-auto-saved))))
  2086.  
  2087. ;; XEmacs change (from Sun)
  2088. ;; used to communicate with continue-save-buffer:
  2089. (defvar continue-save-buffer-hooks-tail nil)
  2090.  
  2091. ;; Not in FSFmacs
  2092. (defun basic-write-file-data (realname truename)
  2093.   ;; call the hooks until the bytes are put
  2094.   ;; call write-region as a last resort
  2095.   (let ((region-written nil)
  2096.     (hooks write-file-data-hooks))
  2097.     (while (and hooks (not region-written))
  2098.       (setq region-written (funcall (car hooks) realname)
  2099.         hooks (cdr hooks)))
  2100.     (if (not region-written)
  2101.     (write-region (point-min) (point-max) realname nil t truename))))
  2102.  
  2103. (put 'after-save-hook 'permanent-local t)
  2104. (defvar after-save-hook nil
  2105.   "Normal hook that is run after a buffer is saved to its file.
  2106. These hooks are considered to pertain to the visited file.
  2107. So this list is cleared if you change the visited file name.")
  2108.  
  2109. (defun files-fetch-hook-value (hook)
  2110.   (let ((localval (symbol-value hook))
  2111.     (globalval (default-value hook)))
  2112.     (if (memq t localval)
  2113.     (setq localval (append (delq t localval) (delq t globalval))))
  2114.     localval))
  2115.   
  2116. (defun basic-save-buffer ()
  2117.   "Save the current buffer in its visited file, if it has been modified.
  2118. After saving the buffer, run `after-save-hook'."
  2119.   (interactive)
  2120.   (save-excursion
  2121.     ;; In an indirect buffer, save its base buffer instead.
  2122.     (if (buffer-base-buffer)
  2123.     (set-buffer (buffer-base-buffer)))
  2124.     (if (buffer-modified-p)
  2125.     (let ((recent-save (recent-auto-save-p)))
  2126.       ;; On VMS, rename file and buffer to get rid of version number.
  2127.       (if (and (eq system-type 'vax-vms)
  2128.            (not (string= buffer-file-name
  2129.                  (file-name-sans-versions buffer-file-name))))
  2130.           (let (buffer-new-name)
  2131.         ;; Strip VMS version number before save.
  2132.         (setq buffer-file-name
  2133.               (file-name-sans-versions buffer-file-name))
  2134.         ;; Construct a (unique) buffer name to correspond.
  2135.         (let ((buf (create-file-buffer (downcase buffer-file-name))))
  2136.           (setq buffer-new-name (buffer-name buf))
  2137.           (kill-buffer buf))
  2138.         (rename-buffer buffer-new-name)))
  2139.       ;; If buffer has no file name, ask user for one.
  2140.       (or buffer-file-name
  2141.           (let ((filename
  2142.              (expand-file-name
  2143.               (read-file-name "File to save in: ") nil)))
  2144.         (and (file-exists-p filename)
  2145.              (or (y-or-n-p (format "File `%s' exists; overwrite? "
  2146.                        filename))
  2147.              (error "Canceled")))
  2148.         (set-visited-file-name filename)))
  2149.       (or (verify-visited-file-modtime (current-buffer))
  2150.           (not (file-exists-p buffer-file-name))
  2151.           (yes-or-no-p
  2152.            (format "%s has changed since visited or saved.  Save anyway? "
  2153.                (file-name-nondirectory buffer-file-name)))
  2154.           (error "Save not confirmed"))
  2155.       (save-restriction
  2156.         (widen)
  2157.         (and (> (point-max) 1)
  2158.          (/= (char-after (1- (point-max))) ?\n)
  2159.          (not (and (eq selective-display t)
  2160.                (= (char-after (1- (point-max))) ?\r)))
  2161.          (or (eq require-final-newline t)
  2162.              (and require-final-newline
  2163.               (y-or-n-p
  2164.                (format "Buffer %s does not end in newline.  Add one? "
  2165.                    (buffer-name)))))
  2166.          (save-excursion
  2167.            (goto-char (point-max))
  2168.            (insert ?\n)))
  2169.         ;;
  2170.         ;; Run the write-file-hooks until one returns non-null.
  2171.         ;; Bind after-save-hook to nil while running the
  2172.         ;; write-file-hooks so that if this function is called
  2173.         ;; recursively (from inside a write-file-hook) the
  2174.         ;; after-hooks will only get run once (from the
  2175.         ;; outermost call).
  2176.         ;;
  2177.         ;; Ugh, have to duplicate logic of run-hook-with-args-until-success
  2178.             (let ((hooks (append (files-fetch-hook-value 'write-contents-hooks)
  2179.                                  (files-fetch-hook-value
  2180.                   'local-write-file-hooks)
  2181.                                  (files-fetch-hook-value 'write-file-hooks)))
  2182.           (after-save-hook nil)
  2183.                   (local-write-file-hooks nil)
  2184.           (write-contents-hooks nil)
  2185.           (write-file-hooks nil)
  2186.           done)
  2187.               (while (and hooks
  2188.                           (let ((continue-save-buffer-hooks-tail hooks))
  2189.                             (not (setq done (funcall (car hooks))))))
  2190.                 (setq hooks (cdr hooks)))
  2191.           ;; If a hook returned t, file is already "written".
  2192.           ;; Otherwise, write it the usual way now.
  2193.           (if (not done)
  2194.           (basic-save-buffer-1)))
  2195.         ;; XEmacs: next two clauses (buffer-file-number setting and
  2196.         ;; set-file-modes) moved into basic-save-buffer-1.
  2197.         )
  2198.       ;; If the auto-save file was recent before this command,
  2199.       ;; delete it now.
  2200.       (delete-auto-save-file-if-necessary recent-save)
  2201.       ;; Support VC `implicit' locking.
  2202.       (when (fboundp 'vc-after-save)
  2203.         (vc-after-save))
  2204.       (run-hooks 'after-save-hook))
  2205.       (display-message 'no-log "(No changes need to be saved)"))))
  2206.  
  2207. ;; This does the "real job" of writing a buffer into its visited file
  2208. ;; and making a backup file.  This is what is normally done
  2209. ;; but inhibited if one of write-file-hooks returns non-nil.
  2210. ;; It returns a value to store in setmodes.
  2211. (defun basic-save-buffer-1 ()
  2212.   (let (setmodes tempsetmodes)
  2213.     (if (not (file-writable-p buffer-file-name))
  2214.     (let ((dir (file-name-directory buffer-file-name)))
  2215.       (if (not (file-directory-p dir))
  2216.           (error "%s is not a directory" dir)
  2217.         (if (not (file-exists-p buffer-file-name))
  2218.         (error "Directory %s write-protected" dir)
  2219.           (if (yes-or-no-p
  2220.            (format "File %s is write-protected; try to save anyway? "
  2221.                (file-name-nondirectory
  2222.                 buffer-file-name)))
  2223.           (setq tempsetmodes t)
  2224.         (error
  2225.          "Attempt to save to a file which you aren't allowed to write"))))))
  2226.     (or buffer-backed-up
  2227.     (setq setmodes (backup-buffer)))
  2228.     (let ((dir (file-name-directory buffer-file-name))) 
  2229.       (if (and file-precious-flag
  2230.            (file-writable-p dir))
  2231.       ;; If file is precious, write temp name, then rename it.
  2232.       ;; This requires write access to the containing dir,
  2233.       ;; which is why we don't try it if we don't have that access.
  2234.       (let ((realname buffer-file-name)
  2235.         tempname nogood i succeed
  2236.         (old-modtime (visited-file-modtime)))
  2237.         (setq i 0)
  2238.         (setq nogood t)
  2239.         ;; Find the temporary name to write under.
  2240.         (while nogood
  2241.           (setq tempname (format "%s#tmp#%d" dir i))
  2242.           (setq nogood (file-exists-p tempname))
  2243.           (setq i (1+ i)))
  2244.         (unwind-protect
  2245.         (progn (clear-visited-file-modtime)
  2246.                (write-region (point-min) (point-max)
  2247.                      tempname nil realname
  2248.                      buffer-file-truename)
  2249.                (setq succeed t))
  2250.           ;; If writing the temp file fails,
  2251.           ;; delete the temp file.
  2252.           (or succeed 
  2253.           (progn
  2254.             (delete-file tempname)
  2255.             (set-visited-file-modtime old-modtime))))
  2256.         ;; Since we have created an entirely new file
  2257.         ;; and renamed it, make sure it gets the
  2258.         ;; right permission bits set.
  2259.         (setq setmodes (file-modes buffer-file-name))
  2260.         ;; We succeeded in writing the temp file,
  2261.         ;; so rename it.
  2262.         (rename-file tempname buffer-file-name t))
  2263.     ;; If file not writable, see if we can make it writable
  2264.     ;; temporarily while we write it.
  2265.     ;; But no need to do so if we have just backed it up
  2266.     ;; (setmodes is set) because that says we're superseding.
  2267.     (cond ((and tempsetmodes (not setmodes))
  2268.            ;; Change the mode back, after writing.
  2269.            (setq setmodes (file-modes buffer-file-name))
  2270.            (set-file-modes buffer-file-name 511)))
  2271.     (basic-write-file-data buffer-file-name buffer-file-truename)))
  2272.     (setq buffer-file-number
  2273.       (if buffer-file-name
  2274.           (nth 10 (file-attributes buffer-file-name))
  2275.         nil))
  2276.     (if setmodes
  2277.     (condition-case ()
  2278.         (set-file-modes buffer-file-name setmodes)
  2279.       (error nil)))))
  2280.  
  2281. ;; XEmacs change, from Sun
  2282. (defun continue-save-buffer ()
  2283.   "Provide a clean way for a write-file-hook to wrap AROUND
  2284. the execution of the remaining hooks and writing to disk.
  2285. Do not call this function except from a functions
  2286. on the write-file-hooks or write-contents-hooks list.
  2287. A hook that calls this function must return non-nil,
  2288. to signal completion to its caller.  continue-save-buffer
  2289. always returns non-nil."
  2290.   (let ((hooks (cdr (or continue-save-buffer-hooks-tail
  2291.             (error
  2292.      "continue-save-buffer called outside a write-file-hook!"))))
  2293.     (done nil))
  2294.     ;; Do something like this:
  2295.     ;; (let ((write-file-hooks hooks)) (basic-save-buffer))
  2296.     ;; First run the rest of the hooks.
  2297.     (while (and hooks
  2298.         (let ((continue-save-buffer-hooks-tail hooks))
  2299.           (not (setq done (funcall (car hooks))))))
  2300.       (setq hooks (cdr hooks)))
  2301.     ;;
  2302.     ;; If a hook returned t, file is already "written".
  2303.     (if (not done)
  2304.     (basic-save-buffer-1))
  2305.     'continue-save-buffer))
  2306.  
  2307. ;; For better or for worse ...
  2308. (defcustom save-some-buffers-query-display-buffer t
  2309.   "*Non-nil makes `\\[save-some-buffers]' switch to the buffer offered for saving."
  2310.   :type 'boolean
  2311.   :group 'editing-basics)
  2312.  
  2313. (defun save-some-buffers (&optional arg exiting)
  2314.   "Save some modified file-visiting buffers.  Asks user about each one.
  2315. Optional argument (the prefix) non-nil means save all with no questions.
  2316. Optional second argument EXITING means ask about certain non-file buffers
  2317.  as well as about file buffers."
  2318.   (interactive "P")
  2319.   (save-excursion
  2320.     (save-window-excursion
  2321.       ;; This can bomb during autoloads generation
  2322.       (when (and (not noninteractive)
  2323.          save-some-buffers-query-display-buffer)
  2324.     (delete-other-windows))
  2325.       ;; XEmacs - do not use queried flag
  2326.       (let ((files-done
  2327.          (map-y-or-n-p
  2328.           (function
  2329.            (lambda (buffer)
  2330.          (and (buffer-modified-p buffer)
  2331.               (not (buffer-base-buffer buffer))
  2332.               ;; XEmacs addition:
  2333.               (not (symbol-value-in-buffer 'save-buffers-skip buffer))
  2334.               (or
  2335.                (buffer-file-name buffer)
  2336.                (and exiting
  2337.                 (progn
  2338.                   (set-buffer buffer)
  2339.                   (and buffer-offer-save (> (buffer-size) 0)))))
  2340.               (if arg
  2341.               t
  2342.             (when save-some-buffers-query-display-buffer
  2343.               (condition-case nil
  2344.                   (switch-to-buffer buffer t)
  2345.                 (error nil)))
  2346.             (if (buffer-file-name buffer)
  2347.                 (format "Save file %s? "
  2348.                     (buffer-file-name buffer))
  2349.               (format "Save buffer %s? "
  2350.                   (buffer-name buffer)))))))
  2351.           (function
  2352.            (lambda (buffer)
  2353.          (set-buffer buffer)
  2354.          (condition-case ()
  2355.              (save-buffer)
  2356.            (error nil))))
  2357.           (buffer-list)
  2358.           '("buffer" "buffers" "save")
  2359.           ;;instead of this we just say "yes all", "no all", etc.
  2360.           ;;"save all the rest"
  2361.           ;;"save only this buffer" "save no more buffers")
  2362.           ;; this is rather bogus. --ben
  2363.           ;; (it makes the dialog box too big, and you get an error
  2364.           ;; "wrong type argument: framep, nil" when you hit q after
  2365.           ;; choosing the option from the dialog box)
  2366. ;        (list (list ?\C-r (lambda (buf)
  2367. ;                (view-buffer buf)
  2368. ;                (setq view-exit-action
  2369. ;                      '(lambda (ignore)
  2370. ;                     (exit-recursive-edit)))
  2371. ;                (recursive-edit)
  2372. ;                ;; Return nil to ask about BUF again.
  2373. ;                nil)
  2374. ;            "display the current buffer"))
  2375.           ))
  2376.         (abbrevs-done
  2377.          (and save-abbrevs abbrevs-changed
  2378.           (progn
  2379.             (if (or arg
  2380.                 (y-or-n-p (format "Save abbrevs in %s? " abbrev-file-name)))
  2381.             (write-abbrev-file nil))
  2382.             ;; Don't keep bothering user if he says no.
  2383.             (setq abbrevs-changed nil)
  2384.             t))))
  2385.     (or (> files-done 0) abbrevs-done
  2386.         (display-message 'no-log "(No files need saving)"))))))
  2387.  
  2388.  
  2389. (defun not-modified (&optional arg)
  2390.   "Mark current buffer as unmodified, not needing to be saved.
  2391. With prefix arg, mark buffer as modified, so \\[save-buffer] will save.
  2392.  
  2393. It is not a good idea to use this function in Lisp programs, because it
  2394. prints a message in the minibuffer.  Instead, use `set-buffer-modified-p'."
  2395.   (interactive "_P")
  2396.   (if arg ;; rewritten for I18N3 snarfing
  2397.       (display-message 'command "Modification-flag set")
  2398.     (display-message 'command "Modification-flag cleared"))
  2399.   (set-buffer-modified-p arg))
  2400.  
  2401. (defun toggle-read-only (&optional arg)
  2402.   "Change whether this buffer is visiting its file read-only.
  2403. With arg, set read-only iff arg is positive."
  2404.   (interactive "_P")
  2405.   (setq buffer-read-only
  2406.     (if (null arg)
  2407.             (not buffer-read-only)
  2408.             (> (prefix-numeric-value arg) 0)))
  2409.   ;; Force modeline redisplay
  2410.   (redraw-modeline))
  2411.  
  2412. (defun insert-file (filename &optional codesys)
  2413.   "Insert contents of file FILENAME into buffer after point.
  2414. Set mark after the inserted text.
  2415.  
  2416. Under XEmacs/Mule, optional second argument specifies the
  2417. coding system to use when decoding the file.  Interactively,
  2418. with a prefix argument, you will be prompted for the coding system.
  2419.  
  2420. This function is meant for the user to run interactively.
  2421. Don't call it from programs!  Use `insert-file-contents' instead.
  2422. \(Its calling sequence is different; see its documentation)."
  2423.   (interactive "*fInsert file: \nZCoding system: ")
  2424.   (if (file-directory-p filename)
  2425.       (signal 'file-error (list "Opening input file" "file is a directory"
  2426.                 filename)))
  2427.   (let* (format-alist ; format.el only confuses people in this context
  2428.      (tem
  2429.      (if codesys
  2430.          (let ((coding-system-for-read
  2431.             (get-coding-system codesys)))
  2432.            (insert-file-contents filename))
  2433.        (insert-file-contents filename))))
  2434.     (push-mark (+ (point) (car (cdr tem))))))
  2435.  
  2436. (defun append-to-file (start end filename &optional codesys)
  2437.   "Append the contents of the region to the end of file FILENAME.
  2438. When called from a function, expects three arguments,
  2439. START, END and FILENAME.  START and END are buffer positions
  2440. saying what text to write.
  2441. Under XEmacs/Mule, optional fourth argument specifies the
  2442. coding system to use when encoding the file.  Interactively,
  2443. with a prefix argument, you will be prompted for the coding system."
  2444.   (interactive "r\nFAppend to file: \nZCoding system: ")
  2445.   (if codesys
  2446.       (let ((buffer-file-coding-system (get-coding-system codesys)))
  2447.     (write-region start end filename t))
  2448.     (write-region start end filename t)))
  2449.  
  2450. (defun file-newest-backup (filename)
  2451.   "Return most recent backup file for FILENAME or nil if no backups exist."
  2452.   (let* ((filename (expand-file-name filename))
  2453.      (file (file-name-nondirectory filename))
  2454.      (dir  (file-name-directory    filename))
  2455.      (comp (file-name-all-completions file dir))
  2456.      newest)
  2457.     (while comp
  2458.       (setq file (concat dir (car comp))
  2459.         comp (cdr comp))
  2460.       (if (and (backup-file-name-p file)
  2461.            (or (null newest) (file-newer-than-file-p file newest)))
  2462.       (setq newest file)))
  2463.     newest))
  2464.  
  2465. (defun rename-uniquely ()
  2466.   "Rename current buffer to a similar name not already taken.
  2467. This function is useful for creating multiple shell process buffers
  2468. or multiple mail buffers, etc."
  2469.   (interactive)
  2470.   (save-match-data
  2471.     (let* ((base-name (if (and (string-match "<[0-9]+>\\'" (buffer-name))
  2472.                    (not (and buffer-file-name
  2473.                      (string= (buffer-name)
  2474.                           (file-name-nondirectory
  2475.                            buffer-file-name)))))
  2476.               ;; If the existing buffer name has a <NNN>,
  2477.               ;; which isn't part of the file name (if any),
  2478.               ;; then get rid of that.
  2479.               (substring (buffer-name) 0 (match-beginning 0))
  2480.             (buffer-name)))
  2481.        (new-buf (generate-new-buffer base-name))
  2482.        (name (buffer-name new-buf)))
  2483.       (kill-buffer new-buf)
  2484.       (rename-buffer name)
  2485.       (redraw-modeline))))
  2486.  
  2487. (defun make-directory-path (path)
  2488.   "Create all the directories along path that don't exist yet."
  2489.   (interactive "Fdirectory path to create: ")
  2490.   (make-directory path t))
  2491.  
  2492. (defun make-directory (dir &optional parents)
  2493.   "Create the directory DIR and any nonexistent parent dirs.
  2494. Interactively, the default choice of directory to create
  2495. is the current default directory for file names.
  2496. That is useful when you have visited a file in a nonexistent directory.
  2497.  
  2498. Noninteractively, the second (optional) argument PARENTS says whether
  2499. to create parent directories if they don't exist."
  2500.   (interactive (list (let ((current-prefix-arg current-prefix-arg))
  2501.                (read-directory-name "Create directory: "))
  2502.              current-prefix-arg))
  2503.   (let ((handler (find-file-name-handler dir 'make-directory)))
  2504.     (if handler
  2505.     (funcall handler 'make-directory dir parents)
  2506.       (if (not parents)
  2507.       (make-directory-internal dir)
  2508.     (let ((dir (directory-file-name (expand-file-name dir)))
  2509.           create-list)
  2510.       (while (not (file-exists-p dir))
  2511.         (setq create-list (cons dir create-list)
  2512.           dir (directory-file-name (file-name-directory dir))))
  2513.       (while create-list
  2514.         (make-directory-internal (car create-list))
  2515.         (setq create-list (cdr create-list))))))))
  2516.  
  2517. (put 'revert-buffer-function 'permanent-local t)
  2518. (defvar revert-buffer-function nil
  2519.   "Function to use to revert this buffer, or nil to do the default.
  2520. The function receives two arguments IGNORE-AUTO and NOCONFIRM,
  2521. which are the arguments that `revert-buffer' received.")
  2522.  
  2523. (put 'revert-buffer-insert-file-contents-function 'permanent-local t)
  2524. (defvar revert-buffer-insert-file-contents-function nil
  2525.   "Function to use to insert contents when reverting this buffer.
  2526. Gets two args, first the nominal file name to use,
  2527. and second, t if reading the auto-save file.")
  2528.  
  2529. (defvar before-revert-hook nil
  2530.   "Normal hook for `revert-buffer' to run before reverting.
  2531. If `revert-buffer-function' is used to override the normal revert
  2532. mechanism, this hook is not used.")
  2533.  
  2534. (defvar after-revert-hook nil
  2535.   "Normal hook for `revert-buffer' to run after reverting.
  2536. Note that the hook value that it runs is the value that was in effect
  2537. before reverting; that makes a difference if you have buffer-local
  2538. hook functions.
  2539.  
  2540. If `revert-buffer-function' is used to override the normal revert
  2541. mechanism, this hook is not used.")
  2542.  
  2543. (defvar revert-buffer-internal-hook nil
  2544.   "Don't use this.")
  2545.  
  2546. (defun revert-buffer (&optional ignore-auto noconfirm preserve-modes)
  2547.   "Replace the buffer text with the text of the visited file on disk.
  2548. This undoes all changes since the file was visited or saved.
  2549. With a prefix argument, offer to revert from latest auto-save file, if
  2550. that is more recent than the visited file.
  2551.  
  2552. This command also works for special buffers that contain text which
  2553. doesn't come from a file, but reflects some other data base instead:
  2554. for example, Dired buffers and buffer-list buffers.  In these cases,
  2555. it reconstructs the buffer contents from the appropriate data base.
  2556.  
  2557. When called from Lisp, the first argument is IGNORE-AUTO; only offer
  2558. to revert from the auto-save file when this is nil.  Note that the
  2559. sense of this argument is the reverse of the prefix argument, for the
  2560. sake of backward compatibility.  IGNORE-AUTO is optional, defaulting
  2561. to nil.
  2562.  
  2563. Optional second argument NOCONFIRM means don't ask for confirmation at
  2564. all.
  2565.  
  2566. Optional third argument PRESERVE-MODES non-nil means don't alter
  2567. the files modes.  Normally we reinitialize them using `normal-mode'.
  2568.  
  2569. If the value of `revert-buffer-function' is non-nil, it is called to
  2570. do the work.
  2571.  
  2572. The default revert function runs the hook `before-revert-hook' at the
  2573. beginning and `after-revert-hook' at the end."
  2574.   ;; I admit it's odd to reverse the sense of the prefix argument, but
  2575.   ;; there is a lot of code out there which assumes that the first
  2576.   ;; argument should be t to avoid consulting the auto-save file, and
  2577.   ;; there's no straightforward way to encourage authors to notice a
  2578.   ;; reversal of the argument sense.  So I'm just changing the user
  2579.   ;; interface, but leaving the programmatic interface the same.
  2580.   (interactive (list (not current-prefix-arg)))
  2581.   (if revert-buffer-function
  2582.       (funcall revert-buffer-function ignore-auto noconfirm)
  2583.     (let* ((opoint (point))
  2584.        (auto-save-p (and (not ignore-auto)
  2585.                              (recent-auto-save-p)
  2586.                  buffer-auto-save-file-name
  2587.                  (file-readable-p buffer-auto-save-file-name)
  2588.                  (y-or-n-p
  2589.    "Buffer has been auto-saved recently.  Revert from auto-save file? ")))
  2590.        (file-name (if auto-save-p
  2591.               buffer-auto-save-file-name
  2592.             buffer-file-name)))
  2593.       (cond ((null file-name)
  2594.          (error "Buffer does not seem to be associated with any file"))
  2595.         ((or noconfirm
  2596.          (and (not (buffer-modified-p))
  2597.               (let (found)
  2598.             (dolist (rx revert-without-query found)
  2599.               (when (string-match rx file-name)
  2600.                 (setq found t)))))
  2601.          (yes-or-no-p (format "Revert buffer from file %s? "
  2602.                       file-name)))
  2603.          (run-hooks 'before-revert-hook)
  2604.          ;; If file was backed up but has changed since,
  2605.          ;; we shd make another backup.
  2606.          (and (not auto-save-p)
  2607.           (not (verify-visited-file-modtime (current-buffer)))
  2608.           (setq buffer-backed-up nil))
  2609.          ;; Get rid of all undo records for this buffer.
  2610.          (or (eq buffer-undo-list t)
  2611.          (setq buffer-undo-list nil))
  2612.          ;; Effectively copy the after-revert-hook status,
  2613.          ;; since after-find-file will clobber it.
  2614.          (let ((global-hook (default-value 'after-revert-hook))
  2615.            (local-hook-p (local-variable-p 'after-revert-hook
  2616.                            (current-buffer)))
  2617.            (local-hook (and (local-variable-p 'after-revert-hook
  2618.                               (current-buffer))
  2619.                     after-revert-hook)))
  2620.            (let (buffer-read-only
  2621.              ;; Don't make undo records for the reversion.
  2622.              (buffer-undo-list t))
  2623.          (if revert-buffer-insert-file-contents-function
  2624.              (funcall revert-buffer-insert-file-contents-function
  2625.                   file-name auto-save-p)
  2626.            (if (not (file-exists-p file-name))
  2627.                (error "File %s no longer exists!" file-name))
  2628.            ;; Bind buffer-file-name to nil
  2629.            ;; so that we don't try to lock the file.
  2630.            (let ((buffer-file-name nil))
  2631.              (or auto-save-p
  2632.              (unlock-buffer)))
  2633.            (widen)
  2634.            (insert-file-contents file-name (not auto-save-p)
  2635.                      nil nil t)))
  2636.            (goto-char (min opoint (point-max)))
  2637.            ;; Recompute the truename in case changes in symlinks
  2638.            ;; have changed the truename.
  2639.            ;XEmacs: already done by insert-file-contents
  2640.            ;;(setq buffer-file-truename
  2641.              ;;(abbreviate-file-name (file-truename buffer-file-name)))
  2642.            (after-find-file nil nil t t preserve-modes)
  2643.            ;; Run after-revert-hook as it was before we reverted.
  2644.            (setq-default revert-buffer-internal-hook global-hook)
  2645.            (if local-hook-p
  2646.            (progn
  2647.              (make-local-variable 'revert-buffer-internal-hook)
  2648.              (setq revert-buffer-internal-hook local-hook))
  2649.          (kill-local-variable 'revert-buffer-internal-hook))
  2650.            (run-hooks 'revert-buffer-internal-hook))
  2651.          t)))))
  2652.  
  2653. (defun recover-file (file)
  2654.   "Visit file FILE, but get contents from its last auto-save file."
  2655.   ;; Actually putting the file name in the minibuffer should be used
  2656.   ;; only rarely.
  2657.   ;; Not just because users often use the default.
  2658.   (interactive "FRecover file: ")
  2659.   (setq file (expand-file-name file))
  2660.   (let ((handler (or (find-file-name-handler file 'recover-file)
  2661.             (find-file-name-handler 
  2662.              (let ((buffer-file-name file))
  2663.                (make-auto-save-file-name))
  2664.              'recover-file))))
  2665.     (if handler
  2666.     (funcall handler 'recover-file file)
  2667.       (if (auto-save-file-name-p file)
  2668.       (error "%s is an auto-save file" file))
  2669.       (let ((file-name (let ((buffer-file-name file))
  2670.              (make-auto-save-file-name))))
  2671.     (cond ((if (file-exists-p file)
  2672.            (not (file-newer-than-file-p file-name file))
  2673.          (not (file-exists-p file-name)))
  2674.            (error "Auto-save file %s not current" file-name))
  2675.           ((save-window-excursion
  2676.          (if (not (eq system-type 'vax-vms))
  2677.              (with-output-to-temp-buffer "*Directory*"
  2678.                (buffer-disable-undo standard-output)
  2679.                (call-process "ls" nil standard-output nil
  2680.                      (if (file-symlink-p file) "-lL" "-l")
  2681.                      file file-name)))
  2682.          (yes-or-no-p (format "Recover auto save file %s? " file-name)))
  2683.            (switch-to-buffer (find-file-noselect file t))
  2684.            (let ((buffer-read-only nil))
  2685.          (erase-buffer)
  2686.          (insert-file-contents file-name nil))
  2687.            (after-find-file nil nil t))
  2688.           (t (error "Recover-file cancelled.")))))))
  2689.  
  2690. (defun recover-session ()
  2691.   "Recover auto save files from a previous Emacs session.
  2692. This command first displays a Dired buffer showing you the
  2693. previous sessions that you could recover from.
  2694. To choose one, move point to the proper line and then type C-c C-c.
  2695. Then you'll be asked about a number of files to recover."
  2696.   (interactive)
  2697.   (dired (concat auto-save-list-file-prefix "*"))
  2698.   (goto-char (point-min))
  2699.   (or (looking-at "Move to the session you want to recover,")
  2700.       (let ((inhibit-read-only t))
  2701.     (insert "Move to the session you want to recover,\n"
  2702.         "then type C-c C-c to select it.\n\n"
  2703.         "You can also delete some of these files;\n"
  2704.         "type d on a line to mark that file for deletion.\n\n")))
  2705.   (use-local-map (let ((map (make-sparse-keymap)))
  2706.            (set-keymap-parents map (list (current-local-map)))
  2707.            map))
  2708.   (define-key (current-local-map) "\C-c\C-c" 'recover-session-finish))
  2709.  
  2710. (defun recover-session-finish ()
  2711.   "Choose one saved session to recover auto-save files from.
  2712. This command is used in the special Dired buffer created by
  2713. \\[recover-session]."
  2714.   (interactive)
  2715.   ;; Get the name of the session file to recover from.
  2716.   (let ((file (dired-get-filename))
  2717.     files
  2718.     (buffer (get-buffer-create " *recover*")))
  2719.     ;; #### dired-do-flagged-delete in FSF.
  2720.     ;; This version is for ange-ftp
  2721.     ;;(dired-do-deletions t)
  2722.     ;; This version is for efs
  2723.     (dired-expunge-deletions)
  2724.     (unwind-protect
  2725.     (save-excursion
  2726.       ;; Read in the auto-save-list file.
  2727.       (set-buffer buffer)
  2728.       (erase-buffer)
  2729.       (insert-file-contents file)
  2730.       ;; Loop thru the text of that file
  2731.       ;; and get out the names of the files to recover.
  2732.       (while (not (eobp))
  2733.         (let (thisfile autofile)
  2734.           (if (eolp)
  2735.           ;; This is a pair of lines for a non-file-visiting buffer.
  2736.           ;; Get the auto-save file name and manufacture
  2737.           ;; a "visited file name" from that.
  2738.           (progn
  2739.             (forward-line 1)
  2740.             (setq autofile
  2741.               (buffer-substring-no-properties
  2742.                (point)
  2743.                (save-excursion
  2744.                  (end-of-line)
  2745.                  (point))))
  2746.             (setq thisfile
  2747.               (expand-file-name
  2748.                (substring
  2749.                 (file-name-nondirectory autofile)
  2750.                 1 -1)
  2751.                (file-name-directory autofile)))
  2752.             (forward-line 1))
  2753.         ;; This pair of lines is a file-visiting
  2754.         ;; buffer.  Use the visited file name.
  2755.         (progn
  2756.           (setq thisfile
  2757.             (buffer-substring-no-properties
  2758.              (point) (progn (end-of-line) (point))))
  2759.           (forward-line 1)
  2760.           (setq autofile
  2761.             (buffer-substring-no-properties
  2762.              (point) (progn (end-of-line) (point))))
  2763.           (forward-line 1)))
  2764.           ;; Ignore a file if its auto-save file does not exist now.
  2765.           (if (file-exists-p autofile)
  2766.           (setq files (cons thisfile files)))))
  2767.       (setq files (nreverse files))
  2768.       ;; The file contains a pair of line for each auto-saved buffer.
  2769.       ;; The first line of the pair contains the visited file name
  2770.       ;; or is empty if the buffer was not visiting a file.
  2771.       ;; The second line is the auto-save file name.
  2772.       (if files
  2773.           (map-y-or-n-p  "Recover %s? "
  2774.                  (lambda (file)
  2775.                    (condition-case nil
  2776.                    (save-excursion (recover-file file))
  2777.                  (error 
  2778.                   "Failed to recover `%s'" file)))
  2779.                  files
  2780.                  '("file" "files" "recover"))
  2781.         (message "No files can be recovered from this session now")))
  2782.       (kill-buffer buffer))))
  2783.  
  2784. (defun kill-some-buffers ()
  2785.   "For each buffer, ask whether to kill it."
  2786.   (interactive)
  2787.   (let ((list (buffer-list)))
  2788.     (while list
  2789.       (let* ((buffer (car list))
  2790.          (name (buffer-name buffer)))
  2791.     (and (not (string-equal name ""))
  2792.          (/= (aref name 0) ? )
  2793.          (yes-or-no-p
  2794.           (format
  2795.            (if (buffer-modified-p buffer)
  2796.            (gettext "Buffer %s HAS BEEN EDITED.  Kill? ")
  2797.            (gettext "Buffer %s is unmodified.  Kill? "))
  2798.               name))
  2799.          (kill-buffer buffer)))
  2800.       (setq list (cdr list)))))
  2801.  
  2802. (defun auto-save-mode (arg)
  2803.   "Toggle auto-saving of contents of current buffer.
  2804. With prefix argument ARG, turn auto-saving on if positive, else off."
  2805.   (interactive "P")
  2806.   (setq buffer-auto-save-file-name
  2807.         (and (if (null arg)
  2808.          (or (not buffer-auto-save-file-name)
  2809.              ;; If autosave is off because buffer has shrunk,
  2810.              ;; then toggling should turn it on.
  2811.              (< buffer-saved-size 0))
  2812.            (or (eq arg t) (listp arg) (and (integerp arg) (> arg 0))))
  2813.          (if (and buffer-file-name auto-save-visited-file-name
  2814.               (not buffer-read-only))
  2815.          buffer-file-name
  2816.            (make-auto-save-file-name))))
  2817.   ;; If -1 was stored here, to temporarily turn off saving,
  2818.   ;; turn it back on.
  2819.   (and (< buffer-saved-size 0)
  2820.        (setq buffer-saved-size 0))
  2821.   (if (interactive-p)
  2822.       (if buffer-auto-save-file-name ;; rewritten for I18N3 snarfing
  2823.       (display-message 'command "Auto-save on (in this buffer)")
  2824.     (display-message 'command "Auto-save off (in this buffer)")))
  2825.   buffer-auto-save-file-name)
  2826.  
  2827. (defun rename-auto-save-file ()
  2828.   "Adjust current buffer's auto save file name for current conditions.
  2829. Also rename any existing auto save file, if it was made in this session."
  2830.   (let ((osave buffer-auto-save-file-name))
  2831.     (setq buffer-auto-save-file-name
  2832.       (make-auto-save-file-name))
  2833.     (if (and osave buffer-auto-save-file-name
  2834.          (not (string= buffer-auto-save-file-name buffer-file-name))
  2835.          (not (string= buffer-auto-save-file-name osave))
  2836.          (file-exists-p osave)
  2837.          (recent-auto-save-p))
  2838.     (rename-file osave buffer-auto-save-file-name t))))
  2839.  
  2840. ;; see also ../packages/auto-save.el
  2841. (defun make-auto-save-file-name (&optional filename)
  2842.   "Return file name to use for auto-saves of current buffer.
  2843. Does not consider `auto-save-visited-file-name' as that variable is checked
  2844. before calling this function.  You can redefine this for customization.
  2845. See also `auto-save-file-name-p'."
  2846.   (let ((fname (or filename buffer-file-name))
  2847.     name)
  2848.     (setq name
  2849.       (if fname
  2850.           (concat (file-name-directory fname)
  2851.               "#"
  2852.               (file-name-nondirectory fname)
  2853.               "#")
  2854.  
  2855.         ;; Deal with buffers that don't have any associated files.  (Mail
  2856.         ;; mode tends to create a good number of these.)
  2857.  
  2858.         (let ((buffer-name (buffer-name))
  2859.           (limit 0))
  2860.           ;; Use technique from Sebastian Kremer's auto-save
  2861.           ;; package to turn slashes into \\!.  This ensures that
  2862.           ;; the auto-save buffer name is unique.
  2863.  
  2864.           ;; #### - yuck!  yuck!  yuck!  move this functionality
  2865.           ;; somewhere else and make the name translation customizable.
  2866.           ;; Using "\!" as part of a filename on a UNIX filesystem is nearly
  2867.           ;; IMPOSSIBLE to get past a shell parser.  -stig
  2868.           
  2869.           (while (string-match "[/\\]" buffer-name limit)
  2870.         (setq buffer-name
  2871.               (concat (substring buffer-name 0 (match-beginning 0))
  2872.                   (if (string= (substring buffer-name
  2873.                               (match-beginning 0)
  2874.                               (match-end 0))
  2875.                        "/")
  2876.                   "\\!"
  2877.                 "\\\\")
  2878.                   (substring buffer-name (match-end 0))))
  2879.         (setq limit (1+ (match-end 0))))
  2880.  
  2881.           ;;    (expand-file-name (format "#%s#%s#" (buffer-name) (make-temp-name "")))
  2882.  
  2883.           ;; jwz: putting the emacs PID in the auto-save file name
  2884.           ;; is bad news, because that defeats auto-save-recovery of
  2885.           ;; *mail* buffers -- the (sensible) code in sendmail.el
  2886.           ;; calls (make-auto-save-file-name) to determine whether
  2887.           ;; there is unsent, auto-saved mail to recover.  If that
  2888.           ;; mail came from a previous emacs process (far and away
  2889.           ;; the most likely case) then this can never succeed as
  2890.           ;; the pid differs.
  2891.           
  2892.           (expand-file-name (format "#%s#" buffer-name)))
  2893.         ))
  2894.     ;; don't try to write auto-save files in unwritable places.  Unless
  2895.     ;; there's already an autosave file here, put ours somewhere safe. --Stig
  2896.     (if (or (file-writable-p name)
  2897.         (file-exists-p name))
  2898.     name
  2899.       (expand-file-name (concat "~/" (file-name-nondirectory name))))))
  2900.  
  2901. (defun auto-save-file-name-p (filename)
  2902.   "Return non-nil if FILENAME can be yielded by `make-auto-save-file-name'.
  2903. FILENAME should lack slashes.
  2904. You can redefine this for customization."
  2905.   (string-match "\\`#.*#\\'" filename))
  2906.  
  2907. (defcustom list-directory-brief-switches
  2908.   (if (eq system-type 'vax-vms) "" "-CF")
  2909.   "*Switches for list-directory to pass to `ls' for brief listing."
  2910.   :type 'string
  2911.   :group 'dired)
  2912.  
  2913. (defcustom list-directory-verbose-switches
  2914.   (if (eq system-type 'vax-vms)
  2915.       "/PROTECTION/SIZE/DATE/OWNER/WIDTH=(OWNER:10)"
  2916.     "-l")
  2917.   "*Switches for list-directory to pass to `ls' for verbose listing,"
  2918.   :type 'string
  2919.   :group 'dired)
  2920.  
  2921. (defun list-directory (dirname &optional verbose)
  2922.   "Display a list of files in or matching DIRNAME, a la `ls'.
  2923. DIRNAME is globbed by the shell if necessary.
  2924. Prefix arg (second arg if noninteractive) means supply -l switch to `ls'.
  2925. Actions controlled by variables `list-directory-brief-switches'
  2926. and `list-directory-verbose-switches'."
  2927.   (interactive (let ((pfx current-prefix-arg))
  2928.          (list (read-file-name (if pfx (gettext "List directory (verbose): ")
  2929.                      (gettext "List directory (brief): "))
  2930.                        nil default-directory nil)
  2931.                pfx)))
  2932.   (let ((switches (if verbose list-directory-verbose-switches
  2933.             list-directory-brief-switches)))
  2934.     (or dirname (setq dirname default-directory))
  2935.     (setq dirname (expand-file-name dirname))
  2936.     (with-output-to-temp-buffer "*Directory*"
  2937.       (buffer-disable-undo standard-output)
  2938.       (princ "Directory ")
  2939.       (princ dirname)
  2940.       (terpri)
  2941.       (save-excursion
  2942.     (set-buffer "*Directory*")
  2943.     (setq default-directory (file-name-directory dirname))
  2944.     (let ((wildcard (not (file-directory-p dirname))))
  2945.       (insert-directory dirname switches wildcard (not wildcard)))))))
  2946.  
  2947. (defvar insert-directory-program "ls"
  2948.   "Absolute or relative name of the `ls' program used by `insert-directory'.")
  2949.  
  2950. ;; insert-directory
  2951. ;; - must insert _exactly_one_line_ describing FILE if WILDCARD and
  2952. ;;   FULL-DIRECTORY-P is nil.
  2953. ;;   The single line of output must display FILE's name as it was
  2954. ;;   given, namely, an absolute path name.
  2955. ;; - must insert exactly one line for each file if WILDCARD or
  2956. ;;   FULL-DIRECTORY-P is t, plus one optional "total" line
  2957. ;;   before the file lines, plus optional text after the file lines.
  2958. ;;   Lines are delimited by "\n", so filenames containing "\n" are not
  2959. ;;   allowed.
  2960. ;;   File lines should display the basename.
  2961. ;; - must be consistent with
  2962. ;;   - functions dired-move-to-filename, (these two define what a file line is)
  2963. ;;            dired-move-to-end-of-filename,
  2964. ;;         dired-between-files, (shortcut for (not (dired-move-to-filename)))
  2965. ;;            dired-insert-headerline
  2966. ;;            dired-after-subdir-garbage (defines what a "total" line is)
  2967. ;;   - variable dired-subdir-regexp
  2968. (defun insert-directory (file switches &optional wildcard full-directory-p)
  2969.   "Insert directory listing for FILE, formatted according to SWITCHES.
  2970. Leaves point after the inserted text.
  2971. SWITCHES may be a string of options, or a list of strings.
  2972. Optional third arg WILDCARD means treat FILE as shell wildcard.
  2973. Optional fourth arg FULL-DIRECTORY-P means file is a directory and
  2974. switches do not contain `d', so that a full listing is expected.
  2975.  
  2976. This works by running a directory listing program
  2977. whose name is in the variable `insert-directory-program'.
  2978. If WILDCARD, it also runs the shell specified by `shell-file-name'."
  2979.   ;; We need the directory in order to find the right handler.
  2980.   (let ((handler (find-file-name-handler (expand-file-name file)
  2981.                      'insert-directory)))
  2982.     (if handler
  2983.     (funcall handler 'insert-directory file switches
  2984.          wildcard full-directory-p)
  2985.       (if (eq system-type 'vax-vms)
  2986.       (vms-read-directory file switches (current-buffer))
  2987.     (if wildcard
  2988.         ;; Run ls in the directory of the file pattern we asked for.
  2989.         (let ((default-directory 
  2990.                       (if (file-name-absolute-p file)
  2991.                           (file-name-directory file)
  2992.                           (file-name-directory (expand-file-name file))))
  2993.           (pattern (file-name-nondirectory file))
  2994.           (beg 0))
  2995.           ;; Quote some characters that have special meanings in shells;
  2996.           ;; but don't quote the wildcards--we want them to be special.
  2997.           ;; We also currently don't quote the quoting characters
  2998.           ;; in case people want to use them explicitly to quote
  2999.           ;; wildcard characters.
  3000.               ;;#### Unix-specific
  3001.           (while (string-match "[ \t\n;<>&|()#$]" pattern beg)
  3002.         (setq pattern
  3003.               (concat (substring pattern 0 (match-beginning 0))
  3004.                   "\\"
  3005.                   (substring pattern (match-beginning 0)))
  3006.               beg (1+ (match-end 0))))
  3007.           (call-process shell-file-name nil t nil
  3008.                 "-c" (concat "\\"  ;; Disregard shell aliases!
  3009.                      insert-directory-program
  3010.                      " -d "
  3011.                      (if (stringp switches)
  3012.                          switches
  3013.                        (mapconcat 'identity switches " "))
  3014.                      " "
  3015.                      pattern)))
  3016.       ;; SunOS 4.1.3, SVr4 and others need the "." to list the
  3017.       ;; directory if FILE is a symbolic link.
  3018.       (apply 'call-process
  3019.          insert-directory-program nil t nil
  3020.          (let (list)
  3021.            (if (listp switches)
  3022.                (setq list switches)
  3023.              (if (not (equal switches ""))
  3024.              (progn
  3025.                ;; Split the switches at any spaces
  3026.                ;; so we can pass separate options as separate args.
  3027.                (while (string-match " " switches)
  3028.                  (setq list (cons (substring switches 0 (match-beginning 0))
  3029.                           list)
  3030.                    switches (substring switches (match-end 0))))
  3031.                (setq list (cons switches list)))))
  3032.            (append list
  3033.                (list
  3034.                 (if full-directory-p
  3035.                 (concat (file-name-as-directory file)
  3036.                     ;;#### Unix-specific
  3037.                     ".")
  3038.                   file))))))))))
  3039.  
  3040. (defvar kill-emacs-query-functions nil
  3041.   "Functions to call with no arguments to query about killing XEmacs.
  3042. If any of these functions returns nil, killing Emacs is cancelled.
  3043. `save-buffers-kill-emacs' (\\[save-buffers-kill-emacs]) calls these functions,
  3044. but `kill-emacs', the low level primitive, does not.
  3045. See also `kill-emacs-hook'.")
  3046.  
  3047. (defun save-buffers-kill-emacs (&optional arg)
  3048.   "Offer to save each buffer, then kill this XEmacs process.
  3049. With prefix arg, silently save all file-visiting buffers, then kill."
  3050.   (interactive "P")
  3051.   (save-some-buffers arg t)
  3052.   (and (or (not (memq t (mapcar #'(lambda (buf) (and (buffer-file-name buf)
  3053.                              (buffer-modified-p buf)))
  3054.                 (buffer-list))))
  3055.        (yes-or-no-p "Modified buffers exist; exit anyway? "))
  3056.        (or (not (fboundp 'process-list))
  3057.        ;; process-list is not defined on VMS.
  3058.        (let ((processes (process-list))
  3059.          active)
  3060.          (while processes
  3061.            (and (memq (process-status (car processes)) '(run stop open))
  3062.             (let ((val (process-kill-without-query (car processes))))
  3063.               (process-kill-without-query (car processes) val)
  3064.               val)
  3065.             (setq active t))
  3066.            (setq processes (cdr processes)))
  3067.          (or
  3068.           (not active)
  3069.           (save-excursion
  3070.         (save-window-excursion
  3071.           (delete-other-windows)
  3072.           (list-processes)
  3073.           (yes-or-no-p
  3074.            "Active processes exist; kill them and exit anyway? "))))))
  3075.        ;; Query the user for other things, perhaps.
  3076.        (run-hook-with-args-until-failure 'kill-emacs-query-functions)
  3077.        (kill-emacs)))
  3078.  
  3079. (defun symlink-expand-file-name (filename)
  3080.   "If FILENAME is a symlink, return its non-symlink equivalent.
  3081. Unlike `file-truename', this doesn't chase symlinks in directory
  3082. components of the file or expand a relative pathname into an
  3083. absolute one."
  3084.   (let ((count 20))
  3085.     (while (and (> count 0) (file-symlink-p filename))
  3086.       (setq filename (file-symlink-p filename)
  3087.         count (1- count)))
  3088.     (if (> count 0)
  3089.     filename
  3090.       (error "Apparently circular symlink path"))))
  3091.  
  3092. ;; Suggested by Michael Kifer <kifer@CS.SunySB.EDU>
  3093. (defun file-remote-p (file-name)
  3094.   "Test whether FILE-NAME is looked for on a remote system."
  3095.   (cond ((not allow-remote-paths) nil)
  3096.     ((featurep 'ange-ftp) (ange-ftp-ftp-path file-name))
  3097.     (t (efs-ftp-path file-name))))
  3098.  
  3099. ;;; files.el ends here
  3100.